wininet: Fix reporting errors in callbacks.
[wine/testsucceed.git] / dlls / ntdll / tests / info.c
blob13c29f831e838aab62cec2f9e6aee84fc8543948
1 /* Unit test suite for *Information* Registry API functions
3 * Copyright 2005 Paul Vriens
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.
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.
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
21 #include "ntdll_test.h"
22 #include <winnls.h>
23 #include <stdio.h>
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 NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *);
32 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
34 static BOOL is_wow64;
36 /* one_before_last_pid is used to be able to compare values of a still running process
37 with the output of the test_query_process_times and test_query_process_handlecount tests.
39 static DWORD one_before_last_pid = 0;
41 #define NTDLL_GET_PROC(func) do { \
42 p ## func = (void*)GetProcAddress(hntdll, #func); \
43 if(!p ## func) { \
44 trace("GetProcAddress(%s) failed\n", #func); \
45 return FALSE; \
46 } \
47 } while(0)
49 static BOOL InitFunctionPtrs(void)
51 /* All needed functions are NT based, so using GetModuleHandle is a good check */
52 HMODULE hntdll = GetModuleHandle("ntdll");
53 if (!hntdll)
55 win_skip("Not running on NT\n");
56 return FALSE;
59 NTDLL_GET_PROC(NtQuerySystemInformation);
60 NTDLL_GET_PROC(NtQueryInformationProcess);
61 NTDLL_GET_PROC(NtQueryInformationThread);
62 NTDLL_GET_PROC(NtSetInformationProcess);
63 NTDLL_GET_PROC(NtSetInformationThread);
64 NTDLL_GET_PROC(NtReadVirtualMemory);
65 NTDLL_GET_PROC(NtQueryVirtualMemory);
67 pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
68 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
69 return TRUE;
72 static void test_query_basic(void)
74 NTSTATUS status;
75 ULONG ReturnLength;
76 SYSTEM_BASIC_INFORMATION sbi;
78 /* This test also covers some basic parameter testing that should be the same for
79 * every information class
82 /* Use a nonexistent info class */
83 trace("Check nonexistent info class\n");
84 status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
85 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
86 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
88 /* Use an existing class but with a zero-length buffer */
89 trace("Check zero-length buffer\n");
90 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
91 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
93 /* Use an existing class, correct length but no SystemInformation buffer */
94 trace("Check no SystemInformation buffer\n");
95 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
96 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER /* vista */,
97 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status);
99 /* Use a existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
100 trace("Check no ReturnLength pointer\n");
101 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
102 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
104 /* Check a too large buffer size */
105 trace("Check a too large buffer size\n");
106 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
107 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
109 /* Finally some correct calls */
110 trace("Check with correct parameters\n");
111 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
112 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
113 ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
115 /* Check if we have some return values */
116 trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
117 ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
120 static void test_query_cpu(void)
122 DWORD status;
123 ULONG ReturnLength;
124 SYSTEM_CPU_INFORMATION sci;
126 status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &ReturnLength);
127 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
128 ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
130 /* Check if we have some return values */
131 trace("Processor FeatureSet : %08x\n", sci.FeatureSet);
132 ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08x\n", sci.FeatureSet);
135 static void test_query_performance(void)
137 NTSTATUS status;
138 ULONG ReturnLength;
139 ULONGLONG buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION)/sizeof(ULONGLONG) + 5];
140 DWORD size = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
142 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, 0, &ReturnLength);
143 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
145 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
146 if (status == STATUS_INFO_LENGTH_MISMATCH && is_wow64)
148 /* size is larger on wow64 under w2k8/win7 */
149 size += 16;
150 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
152 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
153 ok( ReturnLength == size, "Inconsistent length %d\n", ReturnLength);
155 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size + 2, &ReturnLength);
156 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
157 ok( ReturnLength == size || ReturnLength == size + 2,
158 "Inconsistent length %d\n", ReturnLength);
160 /* Not return values yet, as struct members are unknown */
163 static void test_query_timeofday(void)
165 NTSTATUS status;
166 ULONG ReturnLength;
168 /* Copy of our winternl.h structure turned into a private one */
169 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
170 LARGE_INTEGER liKeBootTime;
171 LARGE_INTEGER liKeSystemTime;
172 LARGE_INTEGER liExpTimeZoneBias;
173 ULONG uCurrentTimeZoneId;
174 DWORD dwUnknown1[5];
175 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE, *PSYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
177 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
179 /* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
181 * Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
182 * then 48 and 0 otherwise
183 * Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
184 * and 0 otherwise
186 * Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
187 * NT only fills the buffer if the return code is STATUS_SUCCESS
191 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
193 if (status == STATUS_INFO_LENGTH_MISMATCH)
195 trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
197 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
198 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
199 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
201 sti.uCurrentTimeZoneId = 0xdeadbeef;
202 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
203 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
205 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
206 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
207 ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
209 else
211 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
212 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
213 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
215 sti.uCurrentTimeZoneId = 0xdeadbeef;
216 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 24, &ReturnLength);
217 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
218 ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%d)\n", ReturnLength);
219 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
221 sti.uCurrentTimeZoneId = 0xdeadbeef;
222 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
223 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
224 ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%d)\n", ReturnLength);
225 ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
227 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 49, &ReturnLength);
228 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
229 ok( ReturnLength == 0 || ReturnLength == sizeof(sti) /* vista */,
230 "ReturnLength should be 0, it is (%d)\n", ReturnLength);
232 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
233 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
234 ok( sizeof(sti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
237 /* Check if we have some return values */
238 trace("uCurrentTimeZoneId : (%d)\n", sti.uCurrentTimeZoneId);
241 static void test_query_process(void)
243 NTSTATUS status;
244 DWORD last_pid;
245 ULONG ReturnLength;
246 int i = 0, k = 0;
247 int is_nt = 0;
248 SYSTEM_BASIC_INFORMATION sbi;
250 /* Copy of our winternl.h structure turned into a private one */
251 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
252 ULONG NextEntryOffset;
253 DWORD dwThreadCount;
254 DWORD dwUnknown1[6];
255 FILETIME ftCreationTime;
256 FILETIME ftUserTime;
257 FILETIME ftKernelTime;
258 UNICODE_STRING ProcessName;
259 DWORD dwBasePriority;
260 HANDLE UniqueProcessId;
261 HANDLE ParentProcessId;
262 ULONG HandleCount;
263 DWORD dwUnknown3;
264 DWORD dwUnknown4;
265 VM_COUNTERS vmCounters;
266 IO_COUNTERS ioCounters;
267 SYSTEM_THREAD_INFORMATION ti[1];
268 } SYSTEM_PROCESS_INFORMATION_PRIVATE, *PSYSTEM_PROCESS_INFORMATION_PRIVATE;
270 ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
271 SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
273 /* Only W2K3 returns the needed length, the rest returns 0, so we have to loop */
275 for (;;)
277 status = pNtQuerySystemInformation(SystemProcessInformation, spi_buf, SystemInformationLength, &ReturnLength);
279 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
281 spi_buf = HeapReAlloc(GetProcessHeap(), 0, spi_buf , SystemInformationLength *= 2);
283 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
284 spi = spi_buf;
286 /* Get the first NextEntryOffset, from this we can deduce the OS version we're running
288 * W2K/WinXP/W2K3:
289 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
290 * NT:
291 * NextEntryOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
292 * Wine (with every windows version):
293 * NextEntryOffset for a process is 0 if just this test is running
294 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
295 * ProcessName.MaximumLength
296 * if more wine processes are running
298 * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
301 pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
303 is_nt = ( spi->NextEntryOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136);
305 if (is_nt) win_skip("Windows version is NT, we will skip thread tests\n");
307 /* Check if we have some return values
309 * On windows there will be several processes running (Including the always present Idle and System)
310 * On wine we only have one (if this test is the only wine process running)
313 /* Loop through the processes */
315 for (;;)
317 i++;
319 last_pid = (DWORD_PTR)spi->UniqueProcessId;
321 ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
323 /* Loop through the threads, skip NT4 for now */
325 if (!is_nt)
327 DWORD j;
328 for ( j = 0; j < spi->dwThreadCount; j++)
330 k++;
331 ok ( spi->ti[j].ClientId.UniqueProcess == spi->UniqueProcessId,
332 "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
333 spi->ti[j].ClientId.UniqueProcess, spi->UniqueProcessId);
337 if (!spi->NextEntryOffset) break;
339 one_before_last_pid = last_pid;
341 spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->NextEntryOffset);
343 trace("Total number of running processes : %d\n", i);
344 if (!is_nt) trace("Total number of running threads : %d\n", k);
346 if (one_before_last_pid == 0) one_before_last_pid = last_pid;
348 HeapFree( GetProcessHeap(), 0, spi_buf);
351 static void test_query_procperf(void)
353 NTSTATUS status;
354 ULONG ReturnLength;
355 ULONG NeededLength;
356 SYSTEM_BASIC_INFORMATION sbi;
357 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
359 /* Find out the number of processors */
360 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
361 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
363 sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
365 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
366 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
368 /* Try it for 1 processor */
369 sppi->KernelTime.QuadPart = 0xdeaddead;
370 sppi->UserTime.QuadPart = 0xdeaddead;
371 sppi->IdleTime.QuadPart = 0xdeaddead;
372 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
373 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
374 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
375 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
376 "Inconsistent length %d\n", ReturnLength);
377 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
378 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
379 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
381 /* Try it for all processors */
382 sppi->KernelTime.QuadPart = 0xdeaddead;
383 sppi->UserTime.QuadPart = 0xdeaddead;
384 sppi->IdleTime.QuadPart = 0xdeaddead;
385 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
386 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
387 ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
388 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
389 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
390 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
392 /* A too large given buffer size */
393 sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
394 sppi->KernelTime.QuadPart = 0xdeaddead;
395 sppi->UserTime.QuadPart = 0xdeaddead;
396 sppi->IdleTime.QuadPart = 0xdeaddead;
397 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
398 ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH /* vista */,
399 "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
400 ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
401 if (status == STATUS_SUCCESS)
403 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
404 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
405 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
407 else /* vista and 2008 */
409 ok (sppi->KernelTime.QuadPart == 0xdeaddead, "KernelTime changed\n");
410 ok (sppi->UserTime.QuadPart == 0xdeaddead, "UserTime changed\n");
411 ok (sppi->IdleTime.QuadPart == 0xdeaddead, "IdleTime changed\n");
414 HeapFree( GetProcessHeap(), 0, sppi);
417 static void test_query_module(void)
419 NTSTATUS status;
420 ULONG ReturnLength;
421 ULONG ModuleCount, i;
423 ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
424 SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
425 SYSTEM_MODULE* sm;
427 /* Request the needed length */
428 status = pNtQuerySystemInformation(SystemModuleInformation, smi, 0, &ReturnLength);
429 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
430 ok( ReturnLength > 0, "Expected a ReturnLength to show the needed length\n");
432 SystemInformationLength = ReturnLength;
433 smi = HeapReAlloc(GetProcessHeap(), 0, smi , SystemInformationLength);
434 status = pNtQuerySystemInformation(SystemModuleInformation, smi, SystemInformationLength, &ReturnLength);
435 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
437 ModuleCount = smi->ModulesCount;
438 sm = &smi->Modules[0];
439 /* our implementation is a stub for now */
440 ok( ModuleCount > 0, "Expected some modules to be loaded\n");
442 /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
443 for (i = 0; i < ModuleCount ; i++)
445 ok( i == sm->Id, "Id (%d) should have matched %u\n", sm->Id, i);
446 sm++;
449 HeapFree( GetProcessHeap(), 0, smi);
452 static void test_query_handle(void)
454 NTSTATUS status;
455 ULONG ReturnLength;
456 ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
457 SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
459 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
460 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
461 todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
463 SystemInformationLength = ReturnLength;
464 shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
465 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
466 if (status != STATUS_INFO_LENGTH_MISMATCH) /* vista */
468 ok( status == STATUS_SUCCESS,
469 "Expected STATUS_SUCCESS, got %08x\n", status);
471 /* Check if we have some return values */
472 trace("Number of Handles : %d\n", shi->Count);
473 todo_wine
475 /* our implementation is a stub for now */
476 ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
479 HeapFree( GetProcessHeap(), 0, shi);
482 static void test_query_cache(void)
484 NTSTATUS status;
485 ULONG ReturnLength;
486 SYSTEM_CACHE_INFORMATION sci;
488 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
489 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
491 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
492 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
493 ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
495 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
496 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
497 ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
500 static void test_query_interrupt(void)
502 NTSTATUS status;
503 ULONG ReturnLength;
504 ULONG NeededLength;
505 SYSTEM_BASIC_INFORMATION sbi;
506 SYSTEM_INTERRUPT_INFORMATION* sii;
508 /* Find out the number of processors */
509 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
510 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
512 sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
514 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
515 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
517 /* Try it for all processors */
518 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
519 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
521 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
522 * No test added for this as it's highly unlikely that an app depends on this
525 HeapFree( GetProcessHeap(), 0, sii);
528 static void test_query_kerndebug(void)
530 NTSTATUS status;
531 ULONG ReturnLength;
532 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
534 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
535 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
537 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
538 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
539 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
541 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
542 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
543 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
546 static void test_query_regquota(void)
548 NTSTATUS status;
549 ULONG ReturnLength;
550 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
552 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
553 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
555 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
556 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
557 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
559 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
560 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
561 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
564 static void test_query_process_basic(void)
566 NTSTATUS status;
567 ULONG ReturnLength;
569 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
570 DWORD_PTR ExitStatus;
571 PPEB PebBaseAddress;
572 DWORD_PTR AffinityMask;
573 DWORD_PTR BasePriority;
574 ULONG_PTR UniqueProcessId;
575 ULONG_PTR InheritedFromUniqueProcessId;
576 } PROCESS_BASIC_INFORMATION_PRIVATE, *PPROCESS_BASIC_INFORMATION_PRIVATE;
578 PROCESS_BASIC_INFORMATION_PRIVATE pbi;
580 /* This test also covers some basic parameter testing that should be the same for
581 * every information class
584 /* Use a nonexistent info class */
585 trace("Check nonexistent info class\n");
586 status = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
587 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
588 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
590 /* Do not give a handle and buffer */
591 trace("Check NULL handle and buffer and zero-length buffersize\n");
592 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
593 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
595 /* Use a correct info class and buffer size, but still no handle and buffer */
596 trace("Check NULL handle and buffer\n");
597 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
598 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
599 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
601 /* Use a correct info class and buffer size, but still no handle */
602 trace("Check NULL handle\n");
603 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
604 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
606 /* Use a greater buffer size */
607 trace("Check NULL handle and too large buffersize\n");
608 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
609 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
611 /* Use no ReturnLength */
612 trace("Check NULL ReturnLength\n");
613 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
614 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
616 /* Finally some correct calls */
617 trace("Check with correct parameters\n");
618 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
619 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
620 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
622 /* Everything is correct except a too large buffersize */
623 trace("Too large buffersize\n");
624 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
625 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
626 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
628 /* Check if we have some return values */
629 trace("ProcessID : %lx\n", pbi.UniqueProcessId);
630 ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
633 static void test_query_process_vm(void)
635 NTSTATUS status;
636 ULONG ReturnLength;
637 VM_COUNTERS pvi;
638 ULONG old_size = FIELD_OFFSET(VM_COUNTERS,PrivatePageCount);
640 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
641 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
642 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
644 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, old_size, NULL);
645 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
647 /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
648 Windows W2K will only report success for 44.
649 For now we only care for 44, which is FIELD_OFFSET(VM_COUNTERS,PrivatePageCount))
652 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
653 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
655 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, old_size, &ReturnLength);
656 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
657 ok( old_size == ReturnLength, "Inconsistent length %d\n", ReturnLength);
659 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
660 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
661 ok( ReturnLength == old_size || ReturnLength == sizeof(pvi), "Inconsistent length %d\n", ReturnLength);
663 /* Check if we have some return values */
664 trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
665 todo_wine
667 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
671 static void test_query_process_io(void)
673 NTSTATUS status;
674 ULONG ReturnLength;
675 IO_COUNTERS pii;
677 /* NT4 doesn't support this information class, so check for it */
678 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
679 if (status == STATUS_NOT_SUPPORTED)
681 win_skip("ProcessIoCounters information class is not supported\n");
682 return;
685 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
686 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
687 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
689 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
690 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
692 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
693 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
695 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
696 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
697 ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
699 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
700 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
701 ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
703 /* Check if we have some return values */
704 trace("OtherOperationCount : 0x%x%08x\n", (DWORD)(pii.OtherOperationCount >> 32), (DWORD)pii.OtherOperationCount);
705 todo_wine
707 ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
711 static void test_query_process_times(void)
713 NTSTATUS status;
714 ULONG ReturnLength;
715 HANDLE process;
716 SYSTEMTIME UTC, Local;
717 KERNEL_USER_TIMES spti;
719 status = pNtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
720 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
721 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
723 status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
724 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
726 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
727 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
729 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
730 if (!process)
732 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
733 process = GetCurrentProcess();
734 trace("ProcessTimes for current process\n");
736 else
737 trace("ProcessTimes for process with ID : %d\n", one_before_last_pid);
739 status = pNtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
740 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
741 ok( sizeof(spti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
742 CloseHandle(process);
744 FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
745 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
746 trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
747 Local.wHour, Local.wMinute, Local.wSecond);
749 FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
750 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
751 trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
752 Local.wHour, Local.wMinute, Local.wSecond);
754 FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
755 trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
757 FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
758 trace("UserTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
760 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
761 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
762 ok( sizeof(spti) == ReturnLength ||
763 ReturnLength == 0 /* vista */ ||
764 broken(is_wow64), /* returns garbage on wow64 */
765 "Inconsistent length %d\n", ReturnLength);
768 static void test_query_process_debug_port(int argc, char **argv)
770 DWORD_PTR debug_port = 0xdeadbeef;
771 char cmdline[MAX_PATH];
772 PROCESS_INFORMATION pi;
773 STARTUPINFO si = { 0 };
774 NTSTATUS status;
775 BOOL ret;
777 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
779 si.cb = sizeof(si);
780 ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
781 ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
782 if (!ret) return;
784 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
785 NULL, 0, NULL);
786 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
788 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
789 NULL, sizeof(debug_port), NULL);
790 ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION,
791 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
793 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
794 NULL, sizeof(debug_port), NULL);
795 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
797 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
798 &debug_port, sizeof(debug_port), NULL);
799 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
801 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
802 &debug_port, sizeof(debug_port) - 1, NULL);
803 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
805 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
806 &debug_port, sizeof(debug_port) + 1, NULL);
807 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
809 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
810 &debug_port, sizeof(debug_port), NULL);
811 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
812 ok(debug_port == 0, "Expected port 0, got %#lx.\n", debug_port);
814 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugPort,
815 &debug_port, sizeof(debug_port), NULL);
816 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
817 ok(debug_port == ~(DWORD_PTR)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR)0, debug_port);
819 for (;;)
821 DEBUG_EVENT ev;
823 ret = WaitForDebugEvent(&ev, INFINITE);
824 ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
825 if (!ret) break;
827 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
829 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
830 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
831 if (!ret) break;
834 ret = CloseHandle(pi.hThread);
835 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
836 ret = CloseHandle(pi.hProcess);
837 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
840 static void test_query_process_handlecount(void)
842 NTSTATUS status;
843 ULONG ReturnLength;
844 DWORD handlecount;
845 BYTE buffer[2 * sizeof(DWORD)];
846 HANDLE process;
848 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
849 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
850 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
852 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
853 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
855 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
856 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
858 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
859 if (!process)
861 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
862 process = GetCurrentProcess();
863 trace("ProcessHandleCount for current process\n");
865 else
866 trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid);
868 status = pNtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
869 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
870 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
871 CloseHandle(process);
873 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, buffer, sizeof(buffer), &ReturnLength);
874 ok( status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_SUCCESS,
875 "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08x\n", status);
876 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
878 /* Check if we have some return values */
879 trace("HandleCount : %d\n", handlecount);
880 todo_wine
882 ok( handlecount > 0, "Expected some handles, got 0\n");
886 static void test_query_process_image_file_name(void)
888 NTSTATUS status;
889 ULONG ReturnLength;
890 UNICODE_STRING image_file_name;
891 void *buffer;
892 char *file_nameA;
893 INT len;
895 status = pNtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL);
896 if (status == STATUS_INVALID_INFO_CLASS)
898 win_skip("ProcessImageFileName is not supported\n");
899 return;
901 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
903 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength);
904 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
906 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength);
907 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
909 buffer = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
910 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength);
911 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
912 memcpy(&image_file_name, buffer, sizeof(image_file_name));
913 len = WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), NULL, 0, NULL, NULL);
914 file_nameA = HeapAlloc(GetProcessHeap(), 0, len + 1);
915 WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), file_nameA, len, NULL, NULL);
916 file_nameA[len] = '\0';
917 HeapFree(GetProcessHeap(), 0, buffer);
918 trace("process image file name: %s\n", file_nameA);
919 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);
920 HeapFree(GetProcessHeap(), 0, file_nameA);
924 static void test_readvirtualmemory(void)
926 HANDLE process;
927 NTSTATUS status;
928 SIZE_T readcount;
929 static const char teststring[] = "test string";
930 char buffer[12];
932 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
933 ok(process != 0, "Expected to be able to open own process for reading memory\n");
935 /* normal operation */
936 status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
937 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
938 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
939 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
941 /* no number of bytes */
942 memset(buffer, 0, 12);
943 status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
944 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
945 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
947 /* illegal remote address */
948 todo_wine{
949 status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
950 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION), "Expected STATUS_PARTIAL_COPY, got %08x\n", status);
951 if (status == STATUS_PARTIAL_COPY)
952 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
955 /* 0 handle */
956 status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
957 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
958 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
960 /* pseudo handle for current process*/
961 memset(buffer, 0, 12);
962 status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
963 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
964 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
965 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
967 /* illegal local address */
968 status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
969 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
970 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
972 CloseHandle(process);
975 static void test_queryvirtualmemory(void)
977 NTSTATUS status;
978 SIZE_T readcount;
979 static const char teststring[] = "test string";
980 static char rwtestbuf[42];
981 MEMORY_BASIC_INFORMATION mbi;
982 char stackbuf[42];
984 trace("Check flags of a function entry in NTDLL.DLL\n");
985 status = pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
986 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
987 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
988 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
989 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
990 todo_wine ok (mbi.Protect == PAGE_EXECUTE_READ, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_EXECUTE_READ);
992 trace("Check flags of heap\n");
993 status = pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
994 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
995 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
996 ok (mbi.AllocationProtect == PAGE_READWRITE || mbi.AllocationProtect == PAGE_EXECUTE_READWRITE,
997 "mbi.AllocationProtect is 0x%x\n", mbi.AllocationProtect);
998 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
999 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE,
1000 "mbi.Protect is 0x%x\n", mbi.Protect);
1002 trace("Check flags of stack\n");
1003 status = pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1004 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1005 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1006 ok (mbi.AllocationProtect == PAGE_READWRITE, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READWRITE);
1007 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
1008 ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READWRITE);
1010 trace("Check flags of read-only data\n");
1011 status = pNtQueryVirtualMemory(NtCurrentProcess(), teststring, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1012 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1013 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1014 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1015 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
1016 if (mbi.Protect != PAGE_READONLY)
1017 todo_wine ok( mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x, expected 0x%X\n", mbi.Protect, PAGE_READONLY);
1019 trace("Check flags of read-write global data (.bss)\n");
1020 status = pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1021 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1022 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1023 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1024 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
1025 todo_wine ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%X\n", mbi.Protect, PAGE_READWRITE);
1028 static void test_affinity(void)
1030 NTSTATUS status;
1031 PROCESS_BASIC_INFORMATION pbi;
1032 DWORD_PTR proc_affinity, thread_affinity;
1033 THREAD_BASIC_INFORMATION tbi;
1034 SYSTEM_INFO si;
1036 GetSystemInfo(&si);
1037 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
1038 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1039 proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
1040 ok( proc_affinity == (1 << si.dwNumberOfProcessors) - 1, "Unexpected process affinity\n" );
1041 proc_affinity = 1 << si.dwNumberOfProcessors;
1042 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1043 ok( status == STATUS_INVALID_PARAMETER,
1044 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1046 proc_affinity = 0;
1047 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1048 ok( status == STATUS_INVALID_PARAMETER,
1049 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1051 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1052 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1053 ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1, "Unexpected thread affinity\n" );
1054 thread_affinity = 1 << si.dwNumberOfProcessors;
1055 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1056 ok( status == STATUS_INVALID_PARAMETER,
1057 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1058 thread_affinity = 0;
1059 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1060 ok( status == STATUS_INVALID_PARAMETER,
1061 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1063 thread_affinity = 1;
1064 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1065 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1066 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1067 ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
1069 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
1070 thread_affinity = ~(DWORD_PTR)0;
1071 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1072 ok( broken(status == STATUS_INVALID_PARAMETER) || status == STATUS_SUCCESS,
1073 "Expected STATUS_SUCCESS, got %08x\n", status);
1075 if (si.dwNumberOfProcessors <= 1)
1077 skip("only one processor, skipping affinity testing\n");
1078 return;
1081 /* Test thread affinity mask resulting from "all processors" flag */
1082 if (status == STATUS_SUCCESS)
1084 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1085 ok( broken(tbi.AffinityMask == 1) || tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
1086 "Unexpected thread affinity\n" );
1088 else
1089 skip("Cannot test thread affinity mask for 'all processors' flag\n");
1091 proc_affinity = 2;
1092 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1093 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1094 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
1095 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1096 proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
1097 ok( proc_affinity == 2, "Unexpected process affinity\n" );
1098 /* Setting the process affinity changes the thread affinity to match */
1099 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1100 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1101 ok( tbi.AffinityMask == 2, "Unexpected thread affinity\n" );
1102 /* The thread affinity is restricted to the process affinity */
1103 thread_affinity = 1;
1104 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1105 ok( status == STATUS_INVALID_PARAMETER,
1106 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1108 proc_affinity = (1 << si.dwNumberOfProcessors) - 1;
1109 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1110 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1111 /* Resetting the process affinity also resets the thread affinity */
1112 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1113 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1114 ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
1115 "Unexpected thread affinity\n" );
1118 START_TEST(info)
1120 char **argv;
1121 int argc;
1123 if(!InitFunctionPtrs())
1124 return;
1126 argc = winetest_get_mainargs(&argv);
1127 if (argc >= 3) return; /* Child */
1129 /* NtQuerySystemInformation */
1131 /* 0x0 SystemBasicInformation */
1132 trace("Starting test_query_basic()\n");
1133 test_query_basic();
1135 /* 0x1 SystemCpuInformation */
1136 trace("Starting test_query_cpu()\n");
1137 test_query_cpu();
1139 /* 0x2 SystemPerformanceInformation */
1140 trace("Starting test_query_performance()\n");
1141 test_query_performance();
1143 /* 0x3 SystemTimeOfDayInformation */
1144 trace("Starting test_query_timeofday()\n");
1145 test_query_timeofday();
1147 /* 0x5 SystemProcessInformation */
1148 trace("Starting test_query_process()\n");
1149 test_query_process();
1151 /* 0x8 SystemProcessorPerformanceInformation */
1152 trace("Starting test_query_procperf()\n");
1153 test_query_procperf();
1155 /* 0xb SystemModuleInformation */
1156 trace("Starting test_query_module()\n");
1157 test_query_module();
1159 /* 0x10 SystemHandleInformation */
1160 trace("Starting test_query_handle()\n");
1161 test_query_handle();
1163 /* 0x15 SystemCacheInformation */
1164 trace("Starting test_query_cache()\n");
1165 test_query_cache();
1167 /* 0x17 SystemInterruptInformation */
1168 trace("Starting test_query_interrupt()\n");
1169 test_query_interrupt();
1171 /* 0x23 SystemKernelDebuggerInformation */
1172 trace("Starting test_query_kerndebug()\n");
1173 test_query_kerndebug();
1175 /* 0x25 SystemRegistryQuotaInformation */
1176 trace("Starting test_query_regquota()\n");
1177 test_query_regquota();
1179 /* NtQueryInformationProcess */
1181 /* 0x0 ProcessBasicInformation */
1182 trace("Starting test_query_process_basic()\n");
1183 test_query_process_basic();
1185 /* 0x2 ProcessIoCounters */
1186 trace("Starting test_query_process_io()\n");
1187 test_query_process_io();
1189 /* 0x3 ProcessVmCounters */
1190 trace("Starting test_query_process_vm()\n");
1191 test_query_process_vm();
1193 /* 0x4 ProcessTimes */
1194 trace("Starting test_query_process_times()\n");
1195 test_query_process_times();
1197 /* 0x7 ProcessDebugPort */
1198 trace("Starting test_process_debug_port()\n");
1199 test_query_process_debug_port(argc, argv);
1201 /* 0x14 ProcessHandleCount */
1202 trace("Starting test_query_process_handlecount()\n");
1203 test_query_process_handlecount();
1205 /* 27 ProcessImageFileName */
1206 trace("Starting test_query_process_image_file_name()\n");
1207 test_query_process_image_file_name();
1209 /* belongs into it's own file */
1210 trace("Starting test_readvirtualmemory()\n");
1211 test_readvirtualmemory();
1212 trace("Starting test_queryvirtualmemory()\n");
1213 test_queryvirtualmemory();
1215 trace("Starting test_affinity()\n");
1216 test_affinity();