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"
23 static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
24 static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
25 static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
27 static HMODULE hntdll = 0;
29 /* one_before_last_pid is used to be able to compare values of a still running process
30 with the output of the test_query_process_times and test_query_process_handlecount tests.
32 static DWORD one_before_last_pid = 0;
34 #define NTDLL_GET_PROC(func) \
35 p ## func = (void*)GetProcAddress(hntdll, #func); \
37 trace("GetProcAddress(%s) failed\n", #func); \
38 FreeLibrary(hntdll); \
42 static BOOL InitFunctionPtrs(void)
44 hntdll = LoadLibraryA("ntdll.dll");
46 trace("Could not load ntdll.dll\n");
51 NTDLL_GET_PROC(NtQuerySystemInformation)
52 NTDLL_GET_PROC(NtQueryInformationProcess)
53 NTDLL_GET_PROC(NtReadVirtualMemory)
58 static void test_query_basic(void)
62 SYSTEM_BASIC_INFORMATION sbi;
64 /* This test also covers some basic parameter testing that should be the same for
65 * every information class
68 /* Use a nonexistent info class */
69 trace("Check nonexistent info class\n");
70 status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
71 ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status);
73 /* Use an existing class but with a zero-length buffer */
74 trace("Check zero-length buffer\n");
75 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
76 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
78 /* Use an existing class, correct length but no SystemInformation buffer */
79 trace("Check no SystemInformation buffer\n");
80 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
81 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
83 /* Use a existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
84 trace("Check no ReturnLength pointer\n");
85 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
86 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
88 /* Check a too large buffer size */
89 trace("Check a too large buffer size\n");
90 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
91 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
93 /* Finally some correct calls */
94 trace("Check with correct parameters\n");
95 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
96 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
97 ok( sizeof(sbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
99 /* Check if we have some return values */
100 trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
101 ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
104 static void test_query_cpu(void)
108 SYSTEM_CPU_INFORMATION sci;
110 status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &ReturnLength);
111 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
112 ok( sizeof(sci) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
114 /* Check if we have some return values */
115 trace("Processor FeatureSet : %08lx\n", sci.FeatureSet);
116 ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08lx\n", sci.FeatureSet);
119 static void test_query_performance(void)
123 SYSTEM_PERFORMANCE_INFORMATION spi;
125 status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, 0, &ReturnLength);
126 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
128 status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, sizeof(spi), &ReturnLength);
129 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
130 ok( sizeof(spi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
132 status = pNtQuerySystemInformation(SystemPerformanceInformation, &spi, sizeof(spi) + 2, &ReturnLength);
133 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
134 ok( sizeof(spi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
136 /* Not return values yet, as struct members are unknown */
139 static void test_query_timeofday(void)
144 /* Copy of our winternl.h structure turned into a private one */
145 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
146 LARGE_INTEGER liKeBootTime;
147 LARGE_INTEGER liKeSystemTime;
148 LARGE_INTEGER liExpTimeZoneBias;
149 ULONG uCurrentTimeZoneId;
151 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE, *PSYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
153 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
155 /* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
157 * Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
158 * then 48 and 0 otherwise
159 * Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
162 * Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
163 * NT only fills the buffer if the return code is STATUS_SUCCESS
167 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
169 if (status == STATUS_INFO_LENGTH_MISMATCH)
171 trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
173 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
174 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
175 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
177 sti.uCurrentTimeZoneId = 0xdeadbeef;
178 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
179 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
181 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
182 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
183 ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
187 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
188 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
189 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
191 sti.uCurrentTimeZoneId = 0xdeadbeef;
192 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 24, &ReturnLength);
193 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
194 ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%ld)\n", ReturnLength);
195 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
197 sti.uCurrentTimeZoneId = 0xdeadbeef;
198 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
199 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
200 ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%ld)\n", ReturnLength);
201 ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
203 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 49, &ReturnLength);
204 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
205 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
207 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
208 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
209 ok( sizeof(sti) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
212 /* Check if we have some return values */
213 trace("uCurrentTimeZoneId : (%ld)\n", sti.uCurrentTimeZoneId);
216 static void test_query_process(void)
223 SYSTEM_BASIC_INFORMATION sbi;
225 /* Copy of our winternl.h structure turned into a private one */
226 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
230 FILETIME ftCreationTime;
232 FILETIME ftKernelTime;
233 UNICODE_STRING ProcessName;
234 DWORD dwBasePriority;
236 DWORD dwParentProcessID;
240 VM_COUNTERS vmCounters;
241 IO_COUNTERS ioCounters;
242 SYSTEM_THREAD_INFORMATION ti[1];
243 } SYSTEM_PROCESS_INFORMATION_PRIVATE, *PSYSTEM_PROCESS_INFORMATION_PRIVATE;
245 ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
246 SYSTEM_PROCESS_INFORMATION_PRIVATE* spi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
248 /* Only W2K3 returns the needed length, the rest returns 0, so we have to loop */
252 status = pNtQuerySystemInformation(SystemProcessInformation, spi, SystemInformationLength, &ReturnLength);
254 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
256 spi = HeapReAlloc(GetProcessHeap(), 0, spi , SystemInformationLength *= 2);
259 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
261 /* Get the first dwOffset, from this we can deduce the OS version we're running
264 * dwOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
266 * dwOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
267 * Wine (with every windows version):
268 * dwOffset for a process is 0 if just this test is running
269 * dwOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
270 * ProcessName.MaximumLength
271 * if more wine processes are running
273 * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
276 pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
278 is_nt = ( spi->dwOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136);
280 if (is_nt) trace("Windows version is NT, we will skip thread tests\n");
282 /* Check if we have some return values
284 * On windows there will be several processes running (Including the always present Idle and System)
285 * On wine we only have one (if this test is the only wine process running)
288 /* Loop through the processes */
294 last_pid = spi->dwProcessID;
296 ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
298 /* Loop through the threads, skip NT4 for now */
303 for ( j = 0; j < spi->dwThreadCount; j++)
306 ok ( spi->ti[j].dwOwningPID == spi->dwProcessID,
307 "The owning pid of the thread (%ld) doesn't equal the pid (%ld) of the process\n",
308 spi->ti[j].dwOwningPID, spi->dwProcessID);
312 if (!spi->dwOffset) break;
314 one_before_last_pid = last_pid;
316 spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->dwOffset);
318 trace("Total number of running processes : %d\n", i);
319 if (!is_nt) trace("Total number of running threads : %d\n", k);
321 if (one_before_last_pid == 0) one_before_last_pid = last_pid;
323 HeapFree( GetProcessHeap(), 0, spi);
326 static void test_query_procperf(void)
331 SYSTEM_BASIC_INFORMATION sbi;
332 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
334 /* Find out the number of processors */
335 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
336 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
338 sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
340 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
341 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
343 /* Try it for 1 processor */
344 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
345 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
346 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
347 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
348 "Inconsistent length %ld\n", ReturnLength);
350 /* Try it for all processors */
351 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
352 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
353 ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
355 /* A too large given buffer size */
356 sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
357 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
358 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
359 ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
361 HeapFree( GetProcessHeap(), 0, sppi);
364 static void test_query_module(void)
368 ULONG ModuleCount, i;
370 ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
371 SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
374 /* Request the needed length */
375 status = pNtQuerySystemInformation(SystemModuleInformation, smi, 0, &ReturnLength);
376 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
377 ok( ReturnLength > 0, "Expected a ReturnLength to show the needed length\n");
379 SystemInformationLength = ReturnLength;
380 smi = HeapReAlloc(GetProcessHeap(), 0, smi , SystemInformationLength);
381 status = pNtQuerySystemInformation(SystemModuleInformation, smi, SystemInformationLength, &ReturnLength);
382 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
384 ModuleCount = smi->ModulesCount;
385 sm = &smi->Modules[0];
387 /* our implementation is a stub for now */
388 ok( ModuleCount > 0, "Expected some modules to be loaded\n");
391 /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
392 for (i = 0; i < ModuleCount ; i++)
394 ok( i == sm->Id, "Id (%d) should have matched %lu\n", sm->Id, i);
398 HeapFree( GetProcessHeap(), 0, smi);
401 static void test_query_handle(void)
405 ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
406 SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
408 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
409 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
411 /* The following check assumes more than one handle on any given system */
414 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
416 ok( ReturnLength > 0, "Expected ReturnLength to be > 0, it was %ld\n", ReturnLength);
418 SystemInformationLength = ReturnLength;
419 shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
420 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
421 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
423 /* Check if we have some return values */
424 trace("Number of Handles : %ld\n", shi->Count);
427 /* our implementation is a stub for now */
428 ok( shi->Count > 1, "Expected more than 1 handles, got (%ld)\n", shi->Count);
431 HeapFree( GetProcessHeap(), 0, shi);
434 static void test_query_cache(void)
438 SYSTEM_CACHE_INFORMATION sci;
440 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
441 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
443 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
444 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
445 ok( sizeof(sci) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
447 status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
448 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
449 ok( sizeof(sci) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
452 static void test_query_interrupt(void)
457 SYSTEM_BASIC_INFORMATION sbi;
458 SYSTEM_INTERRUPT_INFORMATION* sii;
460 /* Find out the number of processors */
461 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
462 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
464 sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
466 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
467 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
469 /* Try it for all processors */
470 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
471 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
473 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
474 * No test added for this as it's highly unlikely that an app depends on this
477 HeapFree( GetProcessHeap(), 0, sii);
480 static void test_query_kerndebug(void)
484 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
486 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
487 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
489 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
490 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
491 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
493 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
494 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
495 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
498 static void test_query_regquota(void)
502 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
504 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
505 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
507 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
508 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
509 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
511 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
512 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
513 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
516 static void test_query_process_basic(void)
521 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
523 DWORD PebBaseAddress;
526 ULONG UniqueProcessId;
527 ULONG InheritedFromUniqueProcessId;
528 } PROCESS_BASIC_INFORMATION_PRIVATE, *PPROCESS_BASIC_INFORMATION_PRIVATE;
530 PROCESS_BASIC_INFORMATION_PRIVATE pbi;
532 /* This test also covers some basic parameter testing that should be the same for
533 * every information class
536 /* Use a nonexistent info class */
537 trace("Check nonexistent info class\n");
538 status = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
539 ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status);
541 /* Do not give a handle and buffer */
542 trace("Check NULL handle and buffer and zero-length buffersize\n");
543 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
544 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
546 /* Use a correct info class and buffer size, but still no handle and buffer */
547 trace("Check NULL handle and buffer\n");
548 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
549 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
550 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
552 /* Use a correct info class and buffer size, but still no handle */
553 trace("Check NULL handle\n");
554 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
555 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
557 /* Use a greater buffer size */
558 trace("Check NULL handle and too large buffersize\n");
559 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
560 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
562 /* Use no ReturnLength */
563 trace("Check NULL ReturnLength\n");
564 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
565 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
567 /* Finally some correct calls */
568 trace("Check with correct parameters\n");
569 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
570 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
571 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
573 /* Everything is correct except a too large buffersize */
574 trace("Too large buffersize\n");
575 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
576 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
577 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
579 /* Check if we have some return values */
580 trace("ProcessID : %ld\n", pbi.UniqueProcessId);
581 ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
584 static void test_query_process_vm(void)
590 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
591 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
592 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
594 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
595 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
597 /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
598 Windows W2K will only report success for 44.
599 For now we only care for 44, which is sizeof(VM_COUNTERS)
600 If an app depends on it, we have to implement this in ntdll/process.c
603 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
604 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
606 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), &ReturnLength);
607 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
608 ok( sizeof(pvi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
610 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
611 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
612 ok( sizeof(pvi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
614 /* Check if we have some return values */
615 trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
618 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
622 static void test_query_process_io(void)
628 /* NT4 doesn't support this information class, so check for it */
629 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
630 if (status == STATUS_NOT_SUPPORTED)
632 trace("ProcessIoCounters information class not supported, skipping tests\n");
636 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
637 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
638 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
640 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
641 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
643 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
644 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
646 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
647 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
648 ok( sizeof(pii) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
650 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
651 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
652 ok( sizeof(pii) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
654 /* Check if we have some return values */
655 trace("OtherOperationCount : 0x%lx%08lx\n", (DWORD)(pii.OtherOperationCount >> 32), (DWORD)pii.OtherOperationCount);
658 ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
662 static void test_query_process_times(void)
667 SYSTEMTIME UTC, Local;
668 KERNEL_USER_TIMES spti;
670 status = pNtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
671 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
672 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
674 status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
675 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
677 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
678 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
680 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
683 trace("Could not open process with ID : %ld, error : %08lx. Going to use current one.\n", one_before_last_pid, GetLastError());
684 process = GetCurrentProcess();
685 trace("ProcessTimes for current process\n");
688 trace("ProcessTimes for process with ID : %ld\n", one_before_last_pid);
690 status = pNtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
691 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
692 ok( sizeof(spti) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
693 CloseHandle(process);
695 FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
696 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
697 trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
698 Local.wHour, Local.wMinute, Local.wSecond);
700 FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
701 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
702 trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
703 Local.wHour, Local.wMinute, Local.wSecond);
705 FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
706 trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
708 FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
709 trace("UserTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
711 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
712 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
713 ok( sizeof(spti) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
716 static void test_query_process_handlecount(void)
723 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
724 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
725 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
727 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
728 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
730 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
731 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
733 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
736 trace("Could not open process with ID : %ld, error : %08lx. Going to use current one.\n", one_before_last_pid, GetLastError());
737 process = GetCurrentProcess();
738 trace("ProcessHandleCount for current process\n");
741 trace("ProcessHandleCount for process with ID : %ld\n", one_before_last_pid);
743 status = pNtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
744 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
745 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
746 CloseHandle(process);
748 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, sizeof(handlecount) * 2, &ReturnLength);
749 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
750 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
752 /* Check if we have some return values */
753 trace("HandleCount : %ld\n", handlecount);
756 ok( handlecount > 0, "Expected some handles, got 0\n");
761 static void test_readvirtualmemory(void)
766 static const char teststring[] = "test string";
769 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
770 ok(process != 0, "Expected to be able to open own process for reading memory\n");
772 /* normal operation */
773 status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
774 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
775 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
776 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
778 /* no number of bytes */
779 memset(buffer, 0, 12);
780 status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
781 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
782 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
784 /* illegal remote address */
786 status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
787 ok( status == STATUS_PARTIAL_COPY, "Expected STATUS_PARTIAL_COPY, got %08lx\n", status);
788 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
792 status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
793 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
794 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
796 /* pseudo handle for current process*/
797 memset(buffer, 0, 12);
798 status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
799 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
800 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
801 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
803 /* this test currently crashes wine with "wine client error:<process id>: read: Bad address"
804 * because the reply from wine server is directly read into the buffer and that fails with EFAULT
806 /* illegal local address */
807 /*status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
808 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
809 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
812 CloseHandle(process);
817 if(!InitFunctionPtrs())
820 /* NtQuerySystemInformation */
822 /* 0x0 SystemBasicInformation */
823 trace("Starting test_query_basic()\n");
826 /* 0x1 SystemCpuInformation */
827 trace("Starting test_query_cpu()\n");
830 /* 0x2 SystemPerformanceInformation */
831 trace("Starting test_query_performance()\n");
832 test_query_performance();
834 /* 0x3 SystemTimeOfDayInformation */
835 trace("Starting test_query_timeofday()\n");
836 test_query_timeofday();
838 /* 0x5 SystemProcessInformation */
839 trace("Starting test_query_process()\n");
840 test_query_process();
842 /* 0x8 SystemProcessorPerformanceInformation */
843 trace("Starting test_query_procperf()\n");
844 test_query_procperf();
846 /* 0xb SystemModuleInformation */
847 trace("Starting test_query_module()\n");
850 /* 0x10 SystemHandleInformation */
851 trace("Starting test_query_handle()\n");
854 /* 0x15 SystemCacheInformation */
855 trace("Starting test_query_cache()\n");
858 /* 0x17 SystemInterruptInformation */
859 trace("Starting test_query_interrupt()\n");
860 test_query_interrupt();
862 /* 0x23 SystemKernelDebuggerInformation */
863 trace("Starting test_query_kerndebug()\n");
864 test_query_kerndebug();
866 /* 0x25 SystemRegistryQuotaInformation */
867 trace("Starting test_query_regquota()\n");
868 test_query_regquota();
870 /* NtQueryInformationProcess */
872 /* 0x0 ProcessBasicInformation */
873 trace("Starting test_query_process_basic()\n");
874 test_query_process_basic();
876 /* 0x2 ProcessIoCounters */
877 trace("Starting test_query_process_io()\n");
878 test_query_process_io();
880 /* 0x3 ProcessVmCounters */
881 trace("Starting test_query_process_vm()\n");
882 test_query_process_vm();
884 /* 0x4 ProcessTimes */
885 trace("Starting test_query_process_times()\n");
886 test_query_process_times();
888 /* 0x14 ProcessHandleCount */
889 trace("Starting test_query_process_handlecount()\n");
890 test_query_process_handlecount();
892 /* belongs into it's own file */
893 trace("Starting test_readvirtualmemory()\n");
894 test_readvirtualmemory();