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"
25 static NTSTATUS (WINAPI
* pNtQuerySystemInformation
)(SYSTEM_INFORMATION_CLASS
, PVOID
, ULONG
, PULONG
);
26 static NTSTATUS (WINAPI
* pNtQuerySystemInformationEx
)(SYSTEM_INFORMATION_CLASS
, void*, ULONG
, void*, ULONG
, ULONG
*);
27 static NTSTATUS (WINAPI
* pNtPowerInformation
)(POWER_INFORMATION_LEVEL
, PVOID
, ULONG
, PVOID
, ULONG
);
28 static NTSTATUS (WINAPI
* pNtQueryInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
, PULONG
);
29 static NTSTATUS (WINAPI
* pNtQueryInformationThread
)(HANDLE
, THREADINFOCLASS
, PVOID
, ULONG
, PULONG
);
30 static NTSTATUS (WINAPI
* pNtSetInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
);
31 static NTSTATUS (WINAPI
* pNtSetInformationThread
)(HANDLE
, THREADINFOCLASS
, PVOID
, ULONG
);
32 static NTSTATUS (WINAPI
* pNtReadVirtualMemory
)(HANDLE
, const void*, void*, SIZE_T
, SIZE_T
*);
33 static NTSTATUS (WINAPI
* pNtQueryVirtualMemory
)(HANDLE
, LPCVOID
, MEMORY_INFORMATION_CLASS
, PVOID
, SIZE_T
, SIZE_T
*);
34 static NTSTATUS (WINAPI
* pNtCreateSection
)(HANDLE
*,ACCESS_MASK
,const OBJECT_ATTRIBUTES
*,const LARGE_INTEGER
*,ULONG
,ULONG
,HANDLE
);
35 static NTSTATUS (WINAPI
* pNtMapViewOfSection
)(HANDLE
,HANDLE
,PVOID
*,ULONG
,SIZE_T
,const LARGE_INTEGER
*,SIZE_T
*,SECTION_INHERIT
,ULONG
,ULONG
);
36 static NTSTATUS (WINAPI
* pNtUnmapViewOfSection
)(HANDLE
,PVOID
);
37 static NTSTATUS (WINAPI
* pNtClose
)(HANDLE
);
38 static ULONG (WINAPI
* pNtGetCurrentProcessorNumber
)(void);
39 static BOOL (WINAPI
* pIsWow64Process
)(HANDLE
, PBOOL
);
40 static BOOL (WINAPI
* pGetLogicalProcessorInformationEx
)(LOGICAL_PROCESSOR_RELATIONSHIP
,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*,DWORD
*);
44 /* one_before_last_pid is used to be able to compare values of a still running process
45 with the output of the test_query_process_times and test_query_process_handlecount tests.
47 static DWORD one_before_last_pid
= 0;
49 #define NTDLL_GET_PROC(func) do { \
50 p ## func = (void*)GetProcAddress(hntdll, #func); \
52 trace("GetProcAddress(%s) failed\n", #func); \
57 static BOOL
InitFunctionPtrs(void)
59 /* All needed functions are NT based, so using GetModuleHandle is a good check */
60 HMODULE hntdll
= GetModuleHandleA("ntdll");
61 HMODULE hkernel32
= GetModuleHandleA("kernel32");
65 win_skip("Not running on NT\n");
69 NTDLL_GET_PROC(NtQuerySystemInformation
);
70 NTDLL_GET_PROC(NtPowerInformation
);
71 NTDLL_GET_PROC(NtQueryInformationProcess
);
72 NTDLL_GET_PROC(NtQueryInformationThread
);
73 NTDLL_GET_PROC(NtSetInformationProcess
);
74 NTDLL_GET_PROC(NtSetInformationThread
);
75 NTDLL_GET_PROC(NtReadVirtualMemory
);
76 NTDLL_GET_PROC(NtQueryVirtualMemory
);
77 NTDLL_GET_PROC(NtClose
);
78 NTDLL_GET_PROC(NtCreateSection
);
79 NTDLL_GET_PROC(NtMapViewOfSection
);
80 NTDLL_GET_PROC(NtUnmapViewOfSection
);
82 /* not present before XP */
83 pNtGetCurrentProcessorNumber
= (void *) GetProcAddress(hntdll
, "NtGetCurrentProcessorNumber");
85 pIsWow64Process
= (void *)GetProcAddress(hkernel32
, "IsWow64Process");
86 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
88 /* starting with Win7 */
89 pNtQuerySystemInformationEx
= (void *) GetProcAddress(hntdll
, "NtQuerySystemInformationEx");
90 if (!pNtQuerySystemInformationEx
)
91 win_skip("NtQuerySystemInformationEx() is not supported, some tests will be skipped.\n");
93 pGetLogicalProcessorInformationEx
= (void *) GetProcAddress(hkernel32
, "GetLogicalProcessorInformationEx");
98 static void test_query_basic(void)
102 SYSTEM_BASIC_INFORMATION sbi
;
104 /* This test also covers some basic parameter testing that should be the same for
105 * every information class
108 /* Use a nonexistent info class */
109 trace("Check nonexistent info class\n");
110 status
= pNtQuerySystemInformation(-1, NULL
, 0, NULL
);
111 ok( status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
/* vista */,
112 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status
);
114 /* Use an existing class but with a zero-length buffer */
115 trace("Check zero-length buffer\n");
116 status
= pNtQuerySystemInformation(SystemBasicInformation
, NULL
, 0, NULL
);
117 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
119 /* Use an existing class, correct length but no SystemInformation buffer */
120 trace("Check no SystemInformation buffer\n");
121 status
= pNtQuerySystemInformation(SystemBasicInformation
, NULL
, sizeof(sbi
), NULL
);
122 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
/* vista */,
123 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status
);
125 /* Use an existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
126 trace("Check no ReturnLength pointer\n");
127 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), NULL
);
128 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
130 /* Check a too large buffer size */
131 trace("Check a too large buffer size\n");
132 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
) * 2, &ReturnLength
);
133 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
135 /* Finally some correct calls */
136 trace("Check with correct parameters\n");
137 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
138 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
139 ok( sizeof(sbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
141 /* Check if we have some return values */
142 trace("Number of Processors : %d\n", sbi
.NumberOfProcessors
);
143 ok( sbi
.NumberOfProcessors
> 0, "Expected more than 0 processors, got %d\n", sbi
.NumberOfProcessors
);
146 static void test_query_cpu(void)
150 SYSTEM_CPU_INFORMATION sci
;
152 status
= pNtQuerySystemInformation(SystemCpuInformation
, &sci
, sizeof(sci
), &ReturnLength
);
153 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
154 ok( sizeof(sci
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
156 /* Check if we have some return values */
157 trace("Processor FeatureSet : %08x\n", sci
.FeatureSet
);
158 ok( sci
.FeatureSet
!= 0, "Expected some features for this processor, got %08x\n", sci
.FeatureSet
);
161 static void test_query_performance(void)
165 ULONGLONG buffer
[sizeof(SYSTEM_PERFORMANCE_INFORMATION
)/sizeof(ULONGLONG
) + 5];
166 DWORD size
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
168 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, 0, &ReturnLength
);
169 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
171 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
, &ReturnLength
);
172 if (status
== STATUS_INFO_LENGTH_MISMATCH
&& is_wow64
)
174 /* size is larger on wow64 under w2k8/win7 */
176 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
, &ReturnLength
);
178 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
179 ok( ReturnLength
== size
, "Inconsistent length %d\n", ReturnLength
);
181 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
+ 2, &ReturnLength
);
182 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
183 ok( ReturnLength
== size
|| ReturnLength
== size
+ 2,
184 "Inconsistent length %d\n", ReturnLength
);
186 /* Not return values yet, as struct members are unknown */
189 static void test_query_timeofday(void)
194 /* Copy of our winternl.h structure turned into a private one */
195 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE
{
196 LARGE_INTEGER liKeBootTime
;
197 LARGE_INTEGER liKeSystemTime
;
198 LARGE_INTEGER liExpTimeZoneBias
;
199 ULONG uCurrentTimeZoneId
;
201 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE
;
203 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti
;
205 /* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
207 * Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
208 * then 48 and 0 otherwise
209 * Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
212 * Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
213 * NT only fills the buffer if the return code is STATUS_SUCCESS
217 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, sizeof(sti
), &ReturnLength
);
219 if (status
== STATUS_INFO_LENGTH_MISMATCH
)
221 trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
223 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 0, &ReturnLength
);
224 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
225 ok( 0 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
227 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
228 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 28, &ReturnLength
);
229 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_INFO_LENGTH_MISMATCH
/* NT4 */), "Expected STATUS_SUCCESS, got %08x\n", status
);
230 ok( 0xdeadbeef == sti
.uCurrentTimeZoneId
, "This part of the buffer should not have been filled\n");
232 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 32, &ReturnLength
);
233 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
234 ok( 32 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
238 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 0, &ReturnLength
);
239 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
240 ok( 0 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
242 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
243 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 24, &ReturnLength
);
244 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
245 ok( 24 == ReturnLength
, "ReturnLength should be 24, it is (%d)\n", ReturnLength
);
246 ok( 0xdeadbeef == sti
.uCurrentTimeZoneId
, "This part of the buffer should not have been filled\n");
248 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
249 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 32, &ReturnLength
);
250 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
251 ok( 32 == ReturnLength
, "ReturnLength should be 32, it is (%d)\n", ReturnLength
);
252 ok( 0xdeadbeef != sti
.uCurrentTimeZoneId
, "Buffer should have been partially filled\n");
254 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 49, &ReturnLength
);
255 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
256 ok( ReturnLength
== 0 || ReturnLength
== sizeof(sti
) /* vista */,
257 "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
259 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, sizeof(sti
), &ReturnLength
);
260 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
261 ok( sizeof(sti
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
264 /* Check if we have some return values */
265 trace("uCurrentTimeZoneId : (%d)\n", sti
.uCurrentTimeZoneId
);
268 static void test_query_process(void)
275 SYSTEM_BASIC_INFORMATION sbi
;
277 /* Copy of our winternl.h structure turned into a private one */
278 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE
{
279 ULONG NextEntryOffset
;
282 FILETIME ftCreationTime
;
284 FILETIME ftKernelTime
;
285 UNICODE_STRING ProcessName
;
286 DWORD dwBasePriority
;
287 HANDLE UniqueProcessId
;
288 HANDLE ParentProcessId
;
292 VM_COUNTERS vmCounters
;
293 IO_COUNTERS ioCounters
;
294 SYSTEM_THREAD_INFORMATION ti
[1];
295 } SYSTEM_PROCESS_INFORMATION_PRIVATE
;
297 ULONG SystemInformationLength
= sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE
);
298 SYSTEM_PROCESS_INFORMATION_PRIVATE
*spi
, *spi_buf
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
300 /* test ReturnLength */
302 status
= pNtQuerySystemInformation(SystemProcessInformation
, NULL
, 0, &ReturnLength
);
303 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH got %08x\n", status
);
304 ok( ReturnLength
> 0 || broken(ReturnLength
== 0) /* NT4, Win2K */,
305 "Expected a ReturnLength to show the needed length\n");
307 /* W2K3 and later returns the needed length, the rest returns 0, so we have to loop */
310 status
= pNtQuerySystemInformation(SystemProcessInformation
, spi_buf
, SystemInformationLength
, &ReturnLength
);
312 if (status
!= STATUS_INFO_LENGTH_MISMATCH
) break;
314 spi_buf
= HeapReAlloc(GetProcessHeap(), 0, spi_buf
, SystemInformationLength
*= 2);
316 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
319 /* Get the first NextEntryOffset, from this we can deduce the OS version we're running
322 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
324 * NextEntryOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
325 * Wine (with every windows version):
326 * NextEntryOffset for a process is 0 if just this test is running
327 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
328 * ProcessName.MaximumLength
329 * if more wine processes are running
331 * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
334 pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
336 is_nt
= ( spi
->NextEntryOffset
- (sbi
.NumberOfProcessors
* sizeof(SYSTEM_THREAD_INFORMATION
)) == 136);
338 if (is_nt
) win_skip("Windows version is NT, we will skip thread tests\n");
340 /* Check if we have some return values
342 * On windows there will be several processes running (Including the always present Idle and System)
343 * On wine we only have one (if this test is the only wine process running)
346 /* Loop through the processes */
352 last_pid
= (DWORD_PTR
)spi
->UniqueProcessId
;
354 ok( spi
->dwThreadCount
> 0, "Expected some threads for this process, got 0\n");
356 /* Loop through the threads, skip NT4 for now */
361 for ( j
= 0; j
< spi
->dwThreadCount
; j
++)
364 ok ( spi
->ti
[j
].ClientId
.UniqueProcess
== spi
->UniqueProcessId
,
365 "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
366 spi
->ti
[j
].ClientId
.UniqueProcess
, spi
->UniqueProcessId
);
370 if (!spi
->NextEntryOffset
) break;
372 one_before_last_pid
= last_pid
;
374 spi
= (SYSTEM_PROCESS_INFORMATION_PRIVATE
*)((char*)spi
+ spi
->NextEntryOffset
);
376 trace("Total number of running processes : %d\n", i
);
377 if (!is_nt
) trace("Total number of running threads : %d\n", k
);
379 if (one_before_last_pid
== 0) one_before_last_pid
= last_pid
;
381 HeapFree( GetProcessHeap(), 0, spi_buf
);
384 static void test_query_procperf(void)
389 SYSTEM_BASIC_INFORMATION sbi
;
390 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
* sppi
;
392 /* Find out the number of processors */
393 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
394 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
395 NeededLength
= sbi
.NumberOfProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
397 sppi
= HeapAlloc(GetProcessHeap(), 0, NeededLength
);
399 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, 0, &ReturnLength
);
400 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
402 /* Try it for 1 processor */
403 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
404 sppi
->UserTime
.QuadPart
= 0xdeaddead;
405 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
406 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
,
407 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
), &ReturnLength
);
408 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
409 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) == ReturnLength
,
410 "Inconsistent length %d\n", ReturnLength
);
411 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
412 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
413 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
415 /* Try it for all processors */
416 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
417 sppi
->UserTime
.QuadPart
= 0xdeaddead;
418 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
419 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, NeededLength
, &ReturnLength
);
420 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
421 ok( NeededLength
== ReturnLength
, "Inconsistent length (%d) <-> (%d)\n", NeededLength
, ReturnLength
);
422 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
423 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
424 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
426 /* A too large given buffer size */
427 sppi
= HeapReAlloc(GetProcessHeap(), 0, sppi
, NeededLength
+ 2);
428 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
429 sppi
->UserTime
.QuadPart
= 0xdeaddead;
430 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
431 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, NeededLength
+ 2, &ReturnLength
);
432 ok( status
== STATUS_SUCCESS
|| status
== STATUS_INFO_LENGTH_MISMATCH
/* vista */,
433 "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
434 ok( NeededLength
== ReturnLength
, "Inconsistent length (%d) <-> (%d)\n", NeededLength
, ReturnLength
);
435 if (status
== STATUS_SUCCESS
)
437 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
438 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
439 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
441 else /* vista and 2008 */
443 ok (sppi
->KernelTime
.QuadPart
== 0xdeaddead, "KernelTime changed\n");
444 ok (sppi
->UserTime
.QuadPart
== 0xdeaddead, "UserTime changed\n");
445 ok (sppi
->IdleTime
.QuadPart
== 0xdeaddead, "IdleTime changed\n");
448 HeapFree( GetProcessHeap(), 0, sppi
);
451 static void test_query_module(void)
455 ULONG ModuleCount
, i
;
457 ULONG SystemInformationLength
= sizeof(SYSTEM_MODULE_INFORMATION
);
458 SYSTEM_MODULE_INFORMATION
* smi
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
461 /* Request the needed length */
462 status
= pNtQuerySystemInformation(SystemModuleInformation
, smi
, 0, &ReturnLength
);
463 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
464 ok( ReturnLength
> 0, "Expected a ReturnLength to show the needed length\n");
466 SystemInformationLength
= ReturnLength
;
467 smi
= HeapReAlloc(GetProcessHeap(), 0, smi
, SystemInformationLength
);
468 status
= pNtQuerySystemInformation(SystemModuleInformation
, smi
, SystemInformationLength
, &ReturnLength
);
469 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
471 ModuleCount
= smi
->ModulesCount
;
472 sm
= &smi
->Modules
[0];
473 /* our implementation is a stub for now */
474 ok( ModuleCount
> 0, "Expected some modules to be loaded\n");
476 /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
477 for (i
= 0; i
< ModuleCount
; i
++)
479 ok( i
== sm
->Id
, "Id (%d) should have matched %u\n", sm
->Id
, i
);
483 HeapFree( GetProcessHeap(), 0, smi
);
486 static void test_query_handle(void)
489 ULONG ExpectedLength
, ReturnLength
;
490 ULONG SystemInformationLength
= sizeof(SYSTEM_HANDLE_INFORMATION
);
491 SYSTEM_HANDLE_INFORMATION
* shi
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
496 EventHandle
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
497 ok( EventHandle
!= NULL
, "CreateEventA failed %u\n", GetLastError() );
499 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
500 ReturnLength
= 0xdeadbeef;
501 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
502 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
503 ok( ReturnLength
!= 0xdeadbeef, "Expected valid ReturnLength\n" );
505 SystemInformationLength
= ReturnLength
;
506 shi
= HeapReAlloc(GetProcessHeap(), 0, shi
, SystemInformationLength
);
507 memset(shi
, 0x55, SystemInformationLength
);
509 ReturnLength
= 0xdeadbeef;
510 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
511 while (status
== STATUS_INFO_LENGTH_MISMATCH
) /* Vista / 2008 */
513 SystemInformationLength
*= 2;
514 shi
= HeapReAlloc(GetProcessHeap(), 0, shi
, SystemInformationLength
);
515 memset(shi
, 0x55, SystemInformationLength
);
516 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
518 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
519 ExpectedLength
= FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION
, Handle
[shi
->Count
]);
520 ok( ReturnLength
== ExpectedLength
|| broken(ReturnLength
== ExpectedLength
- sizeof(DWORD
)), /* Vista / 2008 */
521 "Expected length %u, got %u\n", ExpectedLength
, ReturnLength
);
522 ok( shi
->Count
> 1, "Expected more than 1 handle, got %u\n", shi
->Count
);
523 ok( shi
->Handle
[1].HandleValue
!= 0x5555 || broken( shi
->Handle
[1].HandleValue
== 0x5555 ), /* Vista / 2008 */
524 "Uninitialized second handle\n" );
525 if (shi
->Handle
[1].HandleValue
== 0x5555)
527 win_skip("Skipping broken SYSTEM_HANDLE_INFORMATION\n");
528 CloseHandle(EventHandle
);
532 for (i
= 0, found
= FALSE
; i
< shi
->Count
&& !found
; i
++)
533 found
= (shi
->Handle
[i
].OwnerPid
== GetCurrentProcessId()) &&
534 ((HANDLE
)(ULONG_PTR
)shi
->Handle
[i
].HandleValue
== EventHandle
);
535 ok( found
, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle
, GetCurrentProcessId() );
538 for (i
= 0; i
< shi
->Count
; i
++)
539 trace( "%d: handle %x pid %x\n", i
, shi
->Handle
[i
].HandleValue
, shi
->Handle
[i
].OwnerPid
);
541 CloseHandle(EventHandle
);
543 ReturnLength
= 0xdeadbeef;
544 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
545 while (status
== STATUS_INFO_LENGTH_MISMATCH
) /* Vista / 2008 */
547 SystemInformationLength
*= 2;
548 shi
= HeapReAlloc(GetProcessHeap(), 0, shi
, SystemInformationLength
);
549 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
551 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
552 for (i
= 0, found
= FALSE
; i
< shi
->Count
&& !found
; i
++)
553 found
= (shi
->Handle
[i
].OwnerPid
== GetCurrentProcessId()) &&
554 ((HANDLE
)(ULONG_PTR
)shi
->Handle
[i
].HandleValue
== EventHandle
);
555 ok( !found
, "Unexpectedly found event handle in handle list\n" );
557 status
= pNtQuerySystemInformation(SystemHandleInformation
, NULL
, SystemInformationLength
, &ReturnLength
);
558 ok( status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
561 HeapFree( GetProcessHeap(), 0, shi
);
564 static void test_query_cache(void)
569 SYSTEM_CACHE_INFORMATION
*sci
= (SYSTEM_CACHE_INFORMATION
*) buffer
;
573 /* the large SYSTEM_CACHE_INFORMATION on WIN64 is not documented */
574 expected
= sizeof(SYSTEM_CACHE_INFORMATION
);
575 for (i
= sizeof(buffer
); i
>= expected
; i
--)
577 ReturnLength
= 0xdeadbeef;
578 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
579 ok(!status
&& (ReturnLength
== expected
),
580 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i
, status
, ReturnLength
, expected
);
583 /* buffer too small for the full result.
584 Up to win7, the function succeeds with a partial result. */
585 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
588 expected
= offsetof(SYSTEM_CACHE_INFORMATION
, MinimumWorkingSet
);
589 for (; i
>= expected
; i
--)
591 ReturnLength
= 0xdeadbeef;
592 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
593 ok(!status
&& (ReturnLength
== expected
),
594 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i
, status
, ReturnLength
, expected
);
598 /* buffer too small for the result, this call will always fail */
599 ReturnLength
= 0xdeadbeef;
600 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
601 ok( status
== STATUS_INFO_LENGTH_MISMATCH
&&
602 ((ReturnLength
== expected
) || broken(!ReturnLength
) || broken(ReturnLength
== 0xfffffff0)),
603 "%d: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", i
, status
, ReturnLength
, expected
);
606 /* this crashes on some vista / win7 machines */
607 ReturnLength
= 0xdeadbeef;
608 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, 0, &ReturnLength
);
609 ok( status
== STATUS_INFO_LENGTH_MISMATCH
&&
610 ((ReturnLength
== expected
) || broken(!ReturnLength
) || broken(ReturnLength
== 0xfffffff0)),
611 "0: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", status
, ReturnLength
, expected
);
615 static void test_query_interrupt(void)
620 SYSTEM_BASIC_INFORMATION sbi
;
621 SYSTEM_INTERRUPT_INFORMATION
* sii
;
623 /* Find out the number of processors */
624 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
625 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
626 NeededLength
= sbi
.NumberOfProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
);
628 sii
= HeapAlloc(GetProcessHeap(), 0, NeededLength
);
630 status
= pNtQuerySystemInformation(SystemInterruptInformation
, sii
, 0, &ReturnLength
);
631 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
633 /* Try it for all processors */
634 status
= pNtQuerySystemInformation(SystemInterruptInformation
, sii
, NeededLength
, &ReturnLength
);
635 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
637 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
638 * No test added for this as it's highly unlikely that an app depends on this
641 HeapFree( GetProcessHeap(), 0, sii
);
644 static void test_query_kerndebug(void)
648 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
;
650 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, 0, &ReturnLength
);
651 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
653 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, sizeof(skdi
), &ReturnLength
);
654 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
655 ok( sizeof(skdi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
657 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, sizeof(skdi
) + 2, &ReturnLength
);
658 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
659 ok( sizeof(skdi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
662 static void test_query_regquota(void)
666 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi
;
668 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, 0, &ReturnLength
);
669 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
671 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, sizeof(srqi
), &ReturnLength
);
672 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
673 ok( sizeof(srqi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
675 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, sizeof(srqi
) + 2, &ReturnLength
);
676 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
677 ok( sizeof(srqi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
680 static void test_query_logicalproc(void)
683 ULONG len
, i
, proc_no
;
684 SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*slpi
;
689 status
= pNtQuerySystemInformation(SystemLogicalProcessorInformation
, NULL
, 0, &len
);
690 if(status
== STATUS_INVALID_INFO_CLASS
)
692 win_skip("SystemLogicalProcessorInformation is not supported\n");
695 if(status
== STATUS_NOT_IMPLEMENTED
)
697 todo_wine
ok(0, "SystemLogicalProcessorInformation is not implemented\n");
700 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
701 ok(len
%sizeof(*slpi
) == 0, "Incorrect length %d\n", len
);
703 slpi
= HeapAlloc(GetProcessHeap(), 0, len
);
704 status
= pNtQuerySystemInformation(SystemLogicalProcessorInformation
, slpi
, len
, &len
);
705 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
708 for(i
=0; i
<len
/sizeof(*slpi
); i
++) {
709 switch(slpi
[i
].Relationship
) {
710 case RelationProcessorCore
:
711 /* Get number of logical processors */
712 for(; slpi
[i
].ProcessorMask
; slpi
[i
].ProcessorMask
/= 2)
713 proc_no
+= slpi
[i
].ProcessorMask
%2;
719 ok(proc_no
> 0, "No processors were found\n");
720 if(si
.dwNumberOfProcessors
<= 32)
721 ok(proc_no
== si
.dwNumberOfProcessors
, "Incorrect number of logical processors: %d, expected %d\n",
722 proc_no
, si
.dwNumberOfProcessors
);
724 HeapFree(GetProcessHeap(), 0, slpi
);
727 static void test_query_logicalprocex(void)
729 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*infoex
, *infoex2
;
730 DWORD relationship
, len2
, len
;
734 if (!pNtQuerySystemInformationEx
)
738 relationship
= RelationProcessorCore
;
739 status
= pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx
, &relationship
, sizeof(relationship
), NULL
, 0, &len
);
740 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "got 0x%08x\n", status
);
741 ok(len
> 0, "got %u\n", len
);
744 relationship
= RelationAll
;
745 status
= pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx
, &relationship
, sizeof(relationship
), NULL
, 0, &len
);
746 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "got 0x%08x\n", status
);
747 ok(len
> 0, "got %u\n", len
);
750 ret
= pGetLogicalProcessorInformationEx(RelationAll
, NULL
, &len2
);
751 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "got %d, error %d\n", ret
, GetLastError());
752 ok(len
== len2
, "got %u, expected %u\n", len2
, len
);
754 if (len
&& len
== len2
) {
757 infoex
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
758 infoex2
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
760 status
= pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx
, &relationship
, sizeof(relationship
), infoex
, len
, &len
);
761 ok(status
== STATUS_SUCCESS
, "got 0x%08x\n", status
);
763 ret
= pGetLogicalProcessorInformationEx(RelationAll
, infoex2
, &len2
);
764 ok(ret
, "got %d, error %d\n", ret
, GetLastError());
765 ok(!memcmp(infoex
, infoex2
, len
), "returned info data mismatch\n");
767 for(i
= 0; status
== STATUS_SUCCESS
&& i
< len
; ){
768 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*ex
= (void*)(((char *)infoex
) + i
);
770 ok(ex
->Relationship
>= RelationProcessorCore
&& ex
->Relationship
<= RelationGroup
,
771 "Got invalid relationship value: 0x%x\n", ex
->Relationship
);
774 ok(0, "got infoex[%u].Size=0\n", i
);
778 trace("infoex[%u].Size: %u\n", i
, ex
->Size
);
779 switch(ex
->Relationship
){
780 case RelationProcessorCore
:
781 case RelationProcessorPackage
:
782 trace("infoex[%u].Relationship: 0x%x (Core == 0x0 or Package == 0x3)\n", i
, ex
->Relationship
);
783 trace("infoex[%u].Processor.Flags: 0x%x\n", i
, ex
->Processor
.Flags
);
784 trace("infoex[%u].Processor.EfficiencyClass: 0x%x\n", i
, ex
->Processor
.EfficiencyClass
);
785 trace("infoex[%u].Processor.GroupCount: 0x%x\n", i
, ex
->Processor
.GroupCount
);
786 for(j
= 0; j
< ex
->Processor
.GroupCount
; ++j
){
787 trace("infoex[%u].Processor.GroupMask[%u].Mask: 0x%lx\n", i
, j
, ex
->Processor
.GroupMask
[j
].Mask
);
788 trace("infoex[%u].Processor.GroupMask[%u].Group: 0x%x\n", i
, j
, ex
->Processor
.GroupMask
[j
].Group
);
791 case RelationNumaNode
:
792 trace("infoex[%u].Relationship: 0x%x (NumaNode)\n", i
, ex
->Relationship
);
793 trace("infoex[%u].NumaNode.NodeNumber: 0x%x\n", i
, ex
->NumaNode
.NodeNumber
);
794 trace("infoex[%u].NumaNode.GroupMask.Mask: 0x%lx\n", i
, ex
->NumaNode
.GroupMask
.Mask
);
795 trace("infoex[%u].NumaNode.GroupMask.Group: 0x%x\n", i
, ex
->NumaNode
.GroupMask
.Group
);
798 trace("infoex[%u].Relationship: 0x%x (Cache)\n", i
, ex
->Relationship
);
799 trace("infoex[%u].Cache.Level: 0x%x\n", i
, ex
->Cache
.Level
);
800 trace("infoex[%u].Cache.Associativity: 0x%x\n", i
, ex
->Cache
.Associativity
);
801 trace("infoex[%u].Cache.LineSize: 0x%x\n", i
, ex
->Cache
.LineSize
);
802 trace("infoex[%u].Cache.CacheSize: 0x%x\n", i
, ex
->Cache
.CacheSize
);
803 trace("infoex[%u].Cache.Type: 0x%x\n", i
, ex
->Cache
.Type
);
804 trace("infoex[%u].Cache.GroupMask.Mask: 0x%lx\n", i
, ex
->Cache
.GroupMask
.Mask
);
805 trace("infoex[%u].Cache.GroupMask.Group: 0x%x\n", i
, ex
->Cache
.GroupMask
.Group
);
808 trace("infoex[%u].Relationship: 0x%x (Group)\n", i
, ex
->Relationship
);
809 trace("infoex[%u].Group.MaximumGroupCount: 0x%x\n", i
, ex
->Group
.MaximumGroupCount
);
810 trace("infoex[%u].Group.ActiveGroupCount: 0x%x\n", i
, ex
->Group
.ActiveGroupCount
);
811 for(j
= 0; j
< ex
->Group
.ActiveGroupCount
; ++j
){
812 trace("infoex[%u].Group.GroupInfo[%u].MaximumProcessorCount: 0x%x\n", i
, j
, ex
->Group
.GroupInfo
[j
].MaximumProcessorCount
);
813 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorCount: 0x%x\n", i
, j
, ex
->Group
.GroupInfo
[j
].ActiveProcessorCount
);
814 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorMask: 0x%lx\n", i
, j
, ex
->Group
.GroupInfo
[j
].ActiveProcessorMask
);
824 HeapFree(GetProcessHeap(), 0, infoex
);
825 HeapFree(GetProcessHeap(), 0, infoex2
);
829 static void test_query_processor_power_info(void)
832 PROCESSOR_POWER_INFORMATION
* ppi
;
838 size
= si
.dwNumberOfProcessors
* sizeof(PROCESSOR_POWER_INFORMATION
);
839 ppi
= HeapAlloc(GetProcessHeap(), 0, size
);
841 /* If size < (sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors), Win7 returns
842 * STATUS_BUFFER_TOO_SMALL. WinXP returns STATUS_SUCCESS for any value of size. It copies as
843 * many whole PROCESSOR_POWER_INFORMATION structures that there is room for. Even if there is
844 * not enough room for one structure, WinXP still returns STATUS_SUCCESS having done nothing.
846 * If ppi == NULL, Win7 returns STATUS_INVALID_PARAMETER while WinXP returns STATUS_SUCCESS
849 * The same behavior is seen with CallNtPowerInformation (in powrprof.dll).
852 if (si
.dwNumberOfProcessors
> 1)
854 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
855 ppi
[i
].Number
= 0xDEADBEEF;
857 /* Call with a buffer size that is large enough to hold at least one but not large
858 * enough to hold them all. This will be STATUS_SUCCESS on WinXP but not on Win7 */
859 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, size
- sizeof(PROCESSOR_POWER_INFORMATION
));
860 if (status
== STATUS_SUCCESS
)
862 /* lax version found on older Windows like WinXP */
863 ok( (ppi
[si
.dwNumberOfProcessors
- 2].Number
!= 0xDEADBEEF) &&
864 (ppi
[si
.dwNumberOfProcessors
- 1].Number
== 0xDEADBEEF),
865 "Expected all but the last record to be overwritten.\n");
867 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, 0, size
);
868 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
870 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
871 ppi
[i
].Number
= 0xDEADBEEF;
872 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, sizeof(PROCESSOR_POWER_INFORMATION
) - 1);
873 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
874 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
875 if (ppi
[i
].Number
!= 0xDEADBEEF) break;
876 ok( i
== si
.dwNumberOfProcessors
, "Expected untouched buffer\n");
880 /* picky version found on newer Windows like Win7 */
881 ok( ppi
[1].Number
== 0xDEADBEEF, "Expected untouched buffer.\n");
882 ok( status
== STATUS_BUFFER_TOO_SMALL
, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status
);
884 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, 0, size
);
885 ok( status
== STATUS_SUCCESS
|| status
== STATUS_INVALID_PARAMETER
, "Got %08x\n", status
);
887 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, 0);
888 ok( status
== STATUS_BUFFER_TOO_SMALL
|| status
== STATUS_INVALID_PARAMETER
, "Got %08x\n", status
);
893 skip("Test needs more than one processor.\n");
896 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, size
);
897 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
899 HeapFree(GetProcessHeap(), 0, ppi
);
902 static void test_query_process_wow64(void)
906 ULONG_PTR pbi
[2], dummy
;
908 memset(&dummy
, 0xcc, sizeof(dummy
));
910 /* Do not give a handle and buffer */
911 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, NULL
, 0, NULL
);
912 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
914 /* Use a correct info class and buffer size, but still no handle and buffer */
915 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, NULL
, sizeof(ULONG_PTR
), NULL
);
916 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
917 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE, got %08x\n", status
);
919 /* Use a correct info class, buffer size and handle, but no buffer */
920 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, NULL
, sizeof(ULONG_PTR
), NULL
);
921 ok( status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
923 /* Use a correct info class, buffer and buffer size, but no handle */
924 pbi
[0] = pbi
[1] = dummy
;
925 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), NULL
);
926 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
927 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
928 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
930 /* Use a greater buffer size */
931 pbi
[0] = pbi
[1] = dummy
;
932 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) + 1, NULL
);
933 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
934 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
935 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
937 /* Use no ReturnLength */
938 pbi
[0] = pbi
[1] = dummy
;
939 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), NULL
);
940 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
941 trace( "Platform is_wow64 %d, ProcessInformation of ProcessWow64Information %lx\n", is_wow64
, pbi
[0]);
942 ok( is_wow64
== (pbi
[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64
, pbi
[0]);
943 ok( pbi
[0] != dummy
, "pbi[0] %lx\n", pbi
[0]);
944 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
945 /* Test written size on 64 bit by checking high 32 bit buffer */
946 if (sizeof(ULONG_PTR
) > sizeof(DWORD
))
948 DWORD
*ptr
= (DWORD
*)pbi
;
949 ok( ptr
[1] != (DWORD
)dummy
, "ptr[1] unchanged!\n");
952 /* Finally some correct calls */
953 pbi
[0] = pbi
[1] = dummy
;
954 ReturnLength
= 0xdeadbeef;
955 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), &ReturnLength
);
956 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
957 ok( is_wow64
== (pbi
[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64
, pbi
[0]);
958 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
959 ok( ReturnLength
== sizeof(ULONG_PTR
), "Inconsistent length %d\n", ReturnLength
);
961 /* Everything is correct except a too small buffer size */
962 pbi
[0] = pbi
[1] = dummy
;
963 ReturnLength
= 0xdeadbeef;
964 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) - 1, &ReturnLength
);
965 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
966 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
967 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
968 todo_wine
ok( ReturnLength
== 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength
);
970 /* Everything is correct except a too large buffer size */
971 pbi
[0] = pbi
[1] = dummy
;
972 ReturnLength
= 0xdeadbeef;
973 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) + 1, &ReturnLength
);
974 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
975 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
976 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
977 todo_wine
ok( ReturnLength
== 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength
);
980 static void test_query_process_basic(void)
985 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE
{
986 DWORD_PTR ExitStatus
;
988 DWORD_PTR AffinityMask
;
989 DWORD_PTR BasePriority
;
990 ULONG_PTR UniqueProcessId
;
991 ULONG_PTR InheritedFromUniqueProcessId
;
992 } PROCESS_BASIC_INFORMATION_PRIVATE
;
994 PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
996 /* This test also covers some basic parameter testing that should be the same for
997 * every information class
1000 /* Use a nonexistent info class */
1001 trace("Check nonexistent info class\n");
1002 status
= pNtQueryInformationProcess(NULL
, -1, NULL
, 0, NULL
);
1003 ok( status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
/* vista */,
1004 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status
);
1006 /* Do not give a handle and buffer */
1007 trace("Check NULL handle and buffer and zero-length buffersize\n");
1008 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, NULL
, 0, NULL
);
1009 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1011 /* Use a correct info class and buffer size, but still no handle and buffer */
1012 trace("Check NULL handle and buffer\n");
1013 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, NULL
, sizeof(pbi
), NULL
);
1014 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1015 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1017 /* Use a correct info class and buffer size, but still no handle */
1018 trace("Check NULL handle\n");
1019 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1020 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1022 /* Use a greater buffer size */
1023 trace("Check NULL handle and too large buffersize\n");
1024 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, &pbi
, sizeof(pbi
) * 2, NULL
);
1025 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1027 /* Use no ReturnLength */
1028 trace("Check NULL ReturnLength\n");
1029 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1030 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1032 /* Finally some correct calls */
1033 trace("Check with correct parameters\n");
1034 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), &ReturnLength
);
1035 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1036 ok( sizeof(pbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1038 /* Everything is correct except a too large buffersize */
1039 trace("Too large buffersize\n");
1040 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
) * 2, &ReturnLength
);
1041 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1042 ok( sizeof(pbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1044 /* Check if we have some return values */
1045 trace("ProcessID : %lx\n", pbi
.UniqueProcessId
);
1046 ok( pbi
.UniqueProcessId
> 0, "Expected a ProcessID > 0, got 0\n");
1049 static void dump_vm_counters(const char *header
, const VM_COUNTERS
*pvi
)
1051 trace("%s:\n", header
);
1052 trace("PeakVirtualSize : %lu\n", pvi
->PeakVirtualSize
);
1053 trace("VirtualSize : %lu\n", pvi
->VirtualSize
);
1054 trace("PageFaultCount : %u\n", pvi
->PageFaultCount
);
1055 trace("PeakWorkingSetSize : %lu\n", pvi
->PeakWorkingSetSize
);
1056 trace("WorkingSetSize : %lu\n", pvi
->WorkingSetSize
);
1057 trace("QuotaPeakPagedPoolUsage : %lu\n", pvi
->QuotaPeakPagedPoolUsage
);
1058 trace("QuotaPagedPoolUsage : %lu\n", pvi
->QuotaPagedPoolUsage
);
1059 trace("QuotaPeakNonPagePoolUsage : %lu\n", pvi
->QuotaPeakNonPagedPoolUsage
);
1060 trace("QuotaNonPagePoolUsage : %lu\n", pvi
->QuotaNonPagedPoolUsage
);
1061 trace("PagefileUsage : %lu\n", pvi
->PagefileUsage
);
1062 trace("PeakPagefileUsage : %lu\n", pvi
->PeakPagefileUsage
);
1065 static void test_query_process_vm(void)
1070 ULONG old_size
= FIELD_OFFSET(VM_COUNTERS
,PrivatePageCount
);
1073 const SIZE_T alloc_size
= 16 * 1024 * 1024;
1076 status
= pNtQueryInformationProcess(NULL
, ProcessVmCounters
, NULL
, sizeof(pvi
), NULL
);
1077 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1078 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1080 status
= pNtQueryInformationProcess(NULL
, ProcessVmCounters
, &pvi
, old_size
, NULL
);
1081 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1083 /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
1084 Windows W2K will only report success for 44.
1085 For now we only care for 44, which is FIELD_OFFSET(VM_COUNTERS,PrivatePageCount))
1088 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, 24, &ReturnLength
);
1089 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1091 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, old_size
, &ReturnLength
);
1092 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1093 ok( old_size
== ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1095 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, 46, &ReturnLength
);
1096 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1097 ok( ReturnLength
== old_size
|| ReturnLength
== sizeof(pvi
), "Inconsistent length %d\n", ReturnLength
);
1099 /* Check if we have some return values */
1100 dump_vm_counters("VM counters for GetCurrentProcess", &pvi
);
1101 ok( pvi
.WorkingSetSize
> 0, "Expected a WorkingSetSize > 0\n");
1102 ok( pvi
.PagefileUsage
> 0, "Expected a PagefileUsage > 0\n");
1104 process
= OpenProcess(PROCESS_VM_READ
, FALSE
, GetCurrentProcessId());
1105 status
= pNtQueryInformationProcess(process
, ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1106 ok( status
== STATUS_ACCESS_DENIED
, "Expected STATUS_ACCESS_DENIED, got %08x\n", status
);
1107 CloseHandle(process
);
1109 process
= OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
, FALSE
, GetCurrentProcessId());
1110 status
= pNtQueryInformationProcess(process
, ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1111 ok( status
== STATUS_SUCCESS
|| broken(!process
) /* XP */, "Expected STATUS_SUCCESS, got %08x\n", status
);
1112 CloseHandle(process
);
1114 memset(&pvi
, 0, sizeof(pvi
));
1115 process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, GetCurrentProcessId());
1116 status
= pNtQueryInformationProcess(process
, ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1117 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1119 /* Check if we have some return values */
1120 dump_vm_counters("VM counters for GetCurrentProcessId", &pvi
);
1121 ok( pvi
.WorkingSetSize
> 0, "Expected a WorkingSetSize > 0\n");
1122 ok( pvi
.PagefileUsage
> 0, "Expected a PagefileUsage > 0\n");
1124 CloseHandle(process
);
1126 /* Check if we have real counters */
1127 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1128 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1129 prev_size
= pvi
.VirtualSize
;
1130 if (winetest_debug
> 1)
1131 dump_vm_counters("VM counters before VirtualAlloc", &pvi
);
1132 ptr
= VirtualAlloc(NULL
, alloc_size
, MEM_COMMIT
| MEM_RESERVE
, PAGE_READWRITE
);
1133 ok( ptr
!= NULL
, "VirtualAlloc failed, err %u\n", GetLastError());
1134 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1135 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1136 if (winetest_debug
> 1)
1137 dump_vm_counters("VM counters after VirtualAlloc", &pvi
);
1138 todo_wine
ok( pvi
.VirtualSize
>= prev_size
+ alloc_size
,
1139 "Expected to be greater than %lu, got %lu\n", prev_size
+ alloc_size
, pvi
.VirtualSize
);
1140 VirtualFree( ptr
, 0, MEM_RELEASE
);
1142 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1143 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1144 prev_size
= pvi
.VirtualSize
;
1145 if (winetest_debug
> 1)
1146 dump_vm_counters("VM counters before VirtualAlloc", &pvi
);
1147 ptr
= VirtualAlloc(NULL
, alloc_size
, MEM_RESERVE
, PAGE_READWRITE
);
1148 ok( ptr
!= NULL
, "VirtualAlloc failed, err %u\n", GetLastError());
1149 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1150 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1151 if (winetest_debug
> 1)
1152 dump_vm_counters("VM counters after VirtualAlloc(MEM_RESERVE)", &pvi
);
1153 todo_wine
ok( pvi
.VirtualSize
>= prev_size
+ alloc_size
,
1154 "Expected to be greater than %lu, got %lu\n", prev_size
+ alloc_size
, pvi
.VirtualSize
);
1155 prev_size
= pvi
.VirtualSize
;
1157 ptr
= VirtualAlloc(ptr
, alloc_size
, MEM_COMMIT
, PAGE_READWRITE
);
1158 ok( ptr
!= NULL
, "VirtualAlloc failed, err %u\n", GetLastError());
1159 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters
, &pvi
, sizeof(pvi
), NULL
);
1160 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1161 if (winetest_debug
> 1)
1162 dump_vm_counters("VM counters after VirtualAlloc(MEM_COMMIT)", &pvi
);
1163 ok( pvi
.VirtualSize
== prev_size
,
1164 "Expected to equal to %lu, got %lu\n", prev_size
, pvi
.VirtualSize
);
1165 VirtualFree( ptr
, 0, MEM_RELEASE
);
1168 static void test_query_process_io(void)
1174 /* NT4 doesn't support this information class, so check for it */
1175 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
), &ReturnLength
);
1176 if (status
== STATUS_NOT_SUPPORTED
)
1178 win_skip("ProcessIoCounters information class is not supported\n");
1182 status
= pNtQueryInformationProcess(NULL
, ProcessIoCounters
, NULL
, sizeof(pii
), NULL
);
1183 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1184 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1186 status
= pNtQueryInformationProcess(NULL
, ProcessIoCounters
, &pii
, sizeof(pii
), NULL
);
1187 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1189 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, 24, &ReturnLength
);
1190 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1192 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
), &ReturnLength
);
1193 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1194 ok( sizeof(pii
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1196 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
) * 2, &ReturnLength
);
1197 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1198 ok( sizeof(pii
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1200 /* Check if we have some return values */
1201 trace("OtherOperationCount : 0x%x%08x\n", (DWORD
)(pii
.OtherOperationCount
>> 32), (DWORD
)pii
.OtherOperationCount
);
1204 ok( pii
.OtherOperationCount
> 0, "Expected an OtherOperationCount > 0\n");
1208 static void test_query_process_times(void)
1213 SYSTEMTIME UTC
, Local
;
1214 KERNEL_USER_TIMES spti
;
1216 status
= pNtQueryInformationProcess(NULL
, ProcessTimes
, NULL
, sizeof(spti
), NULL
);
1217 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1218 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1220 status
= pNtQueryInformationProcess(NULL
, ProcessTimes
, &spti
, sizeof(spti
), NULL
);
1221 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1223 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes
, &spti
, 24, &ReturnLength
);
1224 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1226 process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, one_before_last_pid
);
1229 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid
, GetLastError());
1230 process
= GetCurrentProcess();
1231 trace("ProcessTimes for current process\n");
1234 trace("ProcessTimes for process with ID : %d\n", one_before_last_pid
);
1236 status
= pNtQueryInformationProcess( process
, ProcessTimes
, &spti
, sizeof(spti
), &ReturnLength
);
1237 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1238 ok( sizeof(spti
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1239 CloseHandle(process
);
1241 FileTimeToSystemTime((const FILETIME
*)&spti
.CreateTime
, &UTC
);
1242 SystemTimeToTzSpecificLocalTime(NULL
, &UTC
, &Local
);
1243 trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local
.wMonth
, Local
.wDay
, Local
.wYear
,
1244 Local
.wHour
, Local
.wMinute
, Local
.wSecond
);
1246 FileTimeToSystemTime((const FILETIME
*)&spti
.ExitTime
, &UTC
);
1247 SystemTimeToTzSpecificLocalTime(NULL
, &UTC
, &Local
);
1248 trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local
.wMonth
, Local
.wDay
, Local
.wYear
,
1249 Local
.wHour
, Local
.wMinute
, Local
.wSecond
);
1251 FileTimeToSystemTime((const FILETIME
*)&spti
.KernelTime
, &Local
);
1252 trace("KernelTime : %02d:%02d:%02d.%03d\n", Local
.wHour
, Local
.wMinute
, Local
.wSecond
, Local
.wMilliseconds
);
1254 FileTimeToSystemTime((const FILETIME
*)&spti
.UserTime
, &Local
);
1255 trace("UserTime : %02d:%02d:%02d.%03d\n", Local
.wHour
, Local
.wMinute
, Local
.wSecond
, Local
.wMilliseconds
);
1257 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes
, &spti
, sizeof(spti
) * 2, &ReturnLength
);
1258 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1259 ok( sizeof(spti
) == ReturnLength
||
1260 ReturnLength
== 0 /* vista */ ||
1261 broken(is_wow64
), /* returns garbage on wow64 */
1262 "Inconsistent length %d\n", ReturnLength
);
1265 static void test_query_process_debug_port(int argc
, char **argv
)
1267 DWORD_PTR debug_port
= 0xdeadbeef;
1268 char cmdline
[MAX_PATH
];
1269 PROCESS_INFORMATION pi
;
1270 STARTUPINFOA si
= { 0 };
1274 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1277 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, DEBUG_PROCESS
, NULL
, NULL
, &si
, &pi
);
1278 ok(ret
, "CreateProcess failed, last error %#x.\n", GetLastError());
1281 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1283 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1285 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1286 NULL
, sizeof(debug_port
), NULL
);
1287 ok(status
== STATUS_INVALID_HANDLE
|| status
== STATUS_ACCESS_VIOLATION
,
1288 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1290 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1291 NULL
, sizeof(debug_port
), NULL
);
1292 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status
);
1294 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1295 &debug_port
, sizeof(debug_port
), NULL
);
1296 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1298 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1299 &debug_port
, sizeof(debug_port
) - 1, NULL
);
1300 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1302 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1303 &debug_port
, sizeof(debug_port
) + 1, NULL
);
1304 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1306 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1307 &debug_port
, sizeof(debug_port
), NULL
);
1308 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1309 ok(debug_port
== 0, "Expected port 0, got %#lx.\n", debug_port
);
1311 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugPort
,
1312 &debug_port
, sizeof(debug_port
), NULL
);
1313 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1314 ok(debug_port
== ~(DWORD_PTR
)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR
)0, debug_port
);
1320 ret
= WaitForDebugEvent(&ev
, INFINITE
);
1321 ok(ret
, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1324 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1326 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1327 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1331 ret
= CloseHandle(pi
.hThread
);
1332 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1333 ret
= CloseHandle(pi
.hProcess
);
1334 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1337 static void test_query_process_handlecount(void)
1342 BYTE buffer
[2 * sizeof(DWORD
)];
1345 status
= pNtQueryInformationProcess(NULL
, ProcessHandleCount
, NULL
, sizeof(handlecount
), NULL
);
1346 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1347 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1349 status
= pNtQueryInformationProcess(NULL
, ProcessHandleCount
, &handlecount
, sizeof(handlecount
), NULL
);
1350 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1352 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount
, &handlecount
, 2, &ReturnLength
);
1353 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1355 process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, one_before_last_pid
);
1358 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid
, GetLastError());
1359 process
= GetCurrentProcess();
1360 trace("ProcessHandleCount for current process\n");
1363 trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid
);
1365 status
= pNtQueryInformationProcess( process
, ProcessHandleCount
, &handlecount
, sizeof(handlecount
), &ReturnLength
);
1366 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1367 ok( sizeof(handlecount
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1368 CloseHandle(process
);
1370 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount
, buffer
, sizeof(buffer
), &ReturnLength
);
1371 ok( status
== STATUS_INFO_LENGTH_MISMATCH
|| status
== STATUS_SUCCESS
,
1372 "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08x\n", status
);
1373 ok( sizeof(handlecount
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1375 /* Check if we have some return values */
1376 trace("HandleCount : %d\n", handlecount
);
1379 ok( handlecount
> 0, "Expected some handles, got 0\n");
1383 static void test_query_process_image_file_name(void)
1387 UNICODE_STRING image_file_name
;
1392 status
= pNtQueryInformationProcess(NULL
, ProcessImageFileName
, &image_file_name
, sizeof(image_file_name
), NULL
);
1393 if (status
== STATUS_INVALID_INFO_CLASS
)
1395 win_skip("ProcessImageFileName is not supported\n");
1398 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1400 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, &image_file_name
, 2, &ReturnLength
);
1401 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1403 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, &image_file_name
, sizeof(image_file_name
), &ReturnLength
);
1404 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1406 buffer
= HeapAlloc(GetProcessHeap(), 0, ReturnLength
);
1407 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, buffer
, ReturnLength
, &ReturnLength
);
1408 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1409 memcpy(&image_file_name
, buffer
, sizeof(image_file_name
));
1410 len
= WideCharToMultiByte(CP_ACP
, 0, image_file_name
.Buffer
, image_file_name
.Length
/sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
1411 file_nameA
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
1412 WideCharToMultiByte(CP_ACP
, 0, image_file_name
.Buffer
, image_file_name
.Length
/sizeof(WCHAR
), file_nameA
, len
, NULL
, NULL
);
1413 file_nameA
[len
] = '\0';
1414 HeapFree(GetProcessHeap(), 0, buffer
);
1415 trace("process image file name: %s\n", file_nameA
);
1416 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
);
1417 HeapFree(GetProcessHeap(), 0, file_nameA
);
1420 static void test_query_process_debug_object_handle(int argc
, char **argv
)
1422 char cmdline
[MAX_PATH
];
1423 STARTUPINFOA si
= {0};
1424 PROCESS_INFORMATION pi
;
1426 HANDLE debug_object
;
1429 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1432 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, DEBUG_PROCESS
, NULL
,
1434 ok(ret
, "CreateProcess failed with last error %u\n", GetLastError());
1437 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
, NULL
,
1439 if (status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
)
1441 win_skip("ProcessDebugObjectHandle is not supported\n");
1444 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1445 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n",
1448 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
, NULL
,
1449 sizeof(debug_object
), NULL
);
1450 ok(status
== STATUS_INVALID_HANDLE
||
1451 status
== STATUS_ACCESS_VIOLATION
, /* XP */
1452 "Expected NtQueryInformationProcess to return STATUS_INVALID_HANDLE, got 0x%08x\n", status
);
1454 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1455 ProcessDebugObjectHandle
, NULL
, sizeof(debug_object
), NULL
);
1456 ok(status
== STATUS_ACCESS_VIOLATION
,
1457 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status
);
1459 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
,
1460 &debug_object
, sizeof(debug_object
), NULL
);
1461 ok(status
== STATUS_INVALID_HANDLE
,
1462 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status
);
1464 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1465 ProcessDebugObjectHandle
, &debug_object
,
1466 sizeof(debug_object
) - 1, NULL
);
1467 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1468 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status
);
1470 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1471 ProcessDebugObjectHandle
, &debug_object
,
1472 sizeof(debug_object
) + 1, NULL
);
1473 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1474 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status
);
1476 debug_object
= (HANDLE
)0xdeadbeef;
1477 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1478 ProcessDebugObjectHandle
, &debug_object
,
1479 sizeof(debug_object
), NULL
);
1480 ok(status
== STATUS_PORT_NOT_SET
,
1481 "Expected NtQueryInformationProcess to return STATUS_PORT_NOT_SET, got 0x%08x\n", status
);
1482 ok(debug_object
== NULL
||
1483 broken(debug_object
== (HANDLE
)0xdeadbeef), /* Wow64 */
1484 "Expected debug object handle to be NULL, got %p\n", debug_object
);
1486 debug_object
= (HANDLE
)0xdeadbeef;
1487 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugObjectHandle
,
1488 &debug_object
, sizeof(debug_object
), NULL
);
1490 ok(status
== STATUS_SUCCESS
,
1491 "Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status
);
1493 ok(debug_object
!= NULL
,
1494 "Expected debug object handle to be non-NULL, got %p\n", debug_object
);
1500 ret
= WaitForDebugEvent(&ev
, INFINITE
);
1501 ok(ret
, "WaitForDebugEvent failed with last error %u\n", GetLastError());
1504 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1506 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1507 ok(ret
, "ContinueDebugEvent failed with last error %u\n", GetLastError());
1511 ret
= CloseHandle(pi
.hThread
);
1512 ok(ret
, "CloseHandle failed with last error %u\n", GetLastError());
1513 ret
= CloseHandle(pi
.hProcess
);
1514 ok(ret
, "CloseHandle failed with last error %u\n", GetLastError());
1517 static void test_query_process_debug_flags(int argc
, char **argv
)
1519 static const DWORD test_flags
[] = { DEBUG_PROCESS
,
1520 DEBUG_ONLY_THIS_PROCESS
,
1521 DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
,
1523 DWORD debug_flags
= 0xdeadbeef;
1524 char cmdline
[MAX_PATH
];
1525 PROCESS_INFORMATION pi
;
1526 STARTUPINFOA si
= { 0 };
1533 /* test invalid arguments */
1534 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
, NULL
, 0, NULL
);
1535 ok(status
== STATUS_INFO_LENGTH_MISMATCH
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1536 "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1538 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
, NULL
, sizeof(debug_flags
), NULL
);
1539 ok(status
== STATUS_INVALID_HANDLE
|| status
== STATUS_ACCESS_VIOLATION
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1540 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1542 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1543 NULL
, sizeof(debug_flags
), NULL
);
1544 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status
);
1546 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
,
1547 &debug_flags
, sizeof(debug_flags
), NULL
);
1548 ok(status
== STATUS_INVALID_HANDLE
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1549 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1551 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1552 &debug_flags
, sizeof(debug_flags
) - 1, NULL
);
1553 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1555 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1556 &debug_flags
, sizeof(debug_flags
) + 1, NULL
);
1557 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1559 /* test ProcessDebugFlags of current process */
1560 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1561 &debug_flags
, sizeof(debug_flags
), NULL
);
1562 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1563 ok(debug_flags
== TRUE
, "Expected flag TRUE, got %x.\n", debug_flags
);
1565 for (i
= 0; i
< sizeof(test_flags
)/sizeof(test_flags
[0]); i
++)
1567 DWORD expected_flags
= !(test_flags
[i
] & DEBUG_ONLY_THIS_PROCESS
);
1568 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1571 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, test_flags
[i
], NULL
, NULL
, &si
, &pi
);
1572 ok(ret
, "CreateProcess failed, last error %#x.\n", GetLastError());
1574 if (!(test_flags
[i
] & (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
)))
1576 /* test ProcessDebugFlags before attaching with debugger */
1577 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1578 &debug_flags
, sizeof(debug_flags
), NULL
);
1579 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1580 ok(debug_flags
== TRUE
, "Expected flag TRUE, got %x.\n", debug_flags
);
1582 ret
= DebugActiveProcess(pi
.dwProcessId
);
1583 ok(ret
, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1584 expected_flags
= FALSE
;
1587 /* test ProcessDebugFlags after attaching with debugger */
1588 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1589 &debug_flags
, sizeof(debug_flags
), NULL
);
1590 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1591 ok(debug_flags
== expected_flags
, "Expected flag %x, got %x.\n", expected_flags
, debug_flags
);
1593 if (!(test_flags
[i
] & CREATE_SUSPENDED
))
1595 /* Continue a couple of times to make sure the process is fully initialized,
1596 * otherwise Windows XP deadlocks in the following DebugActiveProcess(). */
1599 ret
= WaitForDebugEvent(&ev
, 1000);
1600 ok(ret
, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1603 if (ev
.dwDebugEventCode
== LOAD_DLL_DEBUG_EVENT
) break;
1605 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1606 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1610 result
= SuspendThread(pi
.hThread
);
1611 ok(result
== 0, "Expected 0, got %u.\n", result
);
1614 ret
= DebugActiveProcessStop(pi
.dwProcessId
);
1615 ok(ret
, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError());
1617 /* test ProcessDebugFlags after detaching debugger */
1618 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1619 &debug_flags
, sizeof(debug_flags
), NULL
);
1620 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1621 ok(debug_flags
== expected_flags
, "Expected flag %x, got %x.\n", expected_flags
, debug_flags
);
1623 ret
= DebugActiveProcess(pi
.dwProcessId
);
1624 ok(ret
, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1626 /* test ProcessDebugFlags after re-attaching debugger */
1627 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1628 &debug_flags
, sizeof(debug_flags
), NULL
);
1629 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1630 ok(debug_flags
== FALSE
, "Expected flag FALSE, got %x.\n", debug_flags
);
1632 result
= ResumeThread(pi
.hThread
);
1633 todo_wine
ok(result
== 2, "Expected 2, got %u.\n", result
);
1635 /* Wait until the process is terminated. On Windows XP the process randomly
1636 * gets stuck in a non-continuable exception, so stop after 100 iterations.
1637 * On Windows 2003, the debugged process disappears (or stops?) without
1638 * any EXIT_PROCESS_DEBUG_EVENT after a couple of events. */
1639 for (j
= 0; j
< 100; j
++)
1641 ret
= WaitForDebugEvent(&ev
, 1000);
1642 ok(ret
|| broken(GetLastError() == ERROR_SEM_TIMEOUT
),
1643 "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1646 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1648 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1649 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1652 ok(j
< 100 || broken(j
>= 100) /* Win XP */, "Expected less than 100 debug events.\n");
1654 /* test ProcessDebugFlags after process has terminated */
1655 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1656 &debug_flags
, sizeof(debug_flags
), NULL
);
1657 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1658 ok(debug_flags
== FALSE
, "Expected flag FALSE, got %x.\n", debug_flags
);
1660 ret
= CloseHandle(pi
.hThread
);
1661 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1662 ret
= CloseHandle(pi
.hProcess
);
1663 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1667 static void test_readvirtualmemory(void)
1672 static const char teststring
[] = "test string";
1675 process
= OpenProcess(PROCESS_VM_READ
, FALSE
, GetCurrentProcessId());
1676 ok(process
!= 0, "Expected to be able to open own process for reading memory\n");
1678 /* normal operation */
1679 status
= pNtReadVirtualMemory(process
, teststring
, buffer
, 12, &readcount
);
1680 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1681 ok( readcount
== 12, "Expected to read 12 bytes, got %ld\n",readcount
);
1682 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1684 /* no number of bytes */
1685 memset(buffer
, 0, 12);
1686 status
= pNtReadVirtualMemory(process
, teststring
, buffer
, 12, NULL
);
1687 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1688 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1690 /* illegal remote address */
1692 status
= pNtReadVirtualMemory(process
, (void *) 0x1234, buffer
, 12, &readcount
);
1693 ok( status
== STATUS_PARTIAL_COPY
|| broken(status
== STATUS_ACCESS_VIOLATION
), "Expected STATUS_PARTIAL_COPY, got %08x\n", status
);
1694 if (status
== STATUS_PARTIAL_COPY
)
1695 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1699 status
= pNtReadVirtualMemory(0, teststring
, buffer
, 12, &readcount
);
1700 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1701 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1703 /* pseudo handle for current process*/
1704 memset(buffer
, 0, 12);
1705 status
= pNtReadVirtualMemory((HANDLE
)-1, teststring
, buffer
, 12, &readcount
);
1706 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1707 ok( readcount
== 12, "Expected to read 12 bytes, got %ld\n",readcount
);
1708 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1710 /* illegal local address */
1711 status
= pNtReadVirtualMemory(process
, teststring
, (void *)0x1234, 12, &readcount
);
1712 ok( status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
1713 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1715 CloseHandle(process
);
1718 static void test_mapprotection(void)
1722 MEMORY_BASIC_INFORMATION info
;
1723 ULONG oldflags
, flagsize
, flags
= MEM_EXECUTE_OPTION_ENABLE
;
1724 LARGE_INTEGER size
, offset
;
1726 SIZE_T retlen
, count
;
1730 skip("No NtClose ... Win98\n");
1733 /* Switch to being a noexec unaware process */
1734 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &oldflags
, sizeof (oldflags
), &flagsize
);
1735 if (status
== STATUS_INVALID_PARAMETER
) {
1736 skip("Invalid Parameter on ProcessExecuteFlags query?\n");
1739 ok( (status
== STATUS_SUCCESS
) || (status
== STATUS_INVALID_INFO_CLASS
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1740 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
) );
1741 ok( (status
== STATUS_SUCCESS
) || (status
== STATUS_INVALID_INFO_CLASS
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1743 size
.u
.LowPart
= 0x2000;
1744 size
.u
.HighPart
= 0;
1745 status
= pNtCreateSection ( &h
,
1746 STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
1750 SEC_COMMIT
| SEC_NOCACHE
,
1753 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1755 offset
.u
.LowPart
= 0;
1756 offset
.u
.HighPart
= 0;
1759 status
= pNtMapViewOfSection ( h
, GetCurrentProcess(), &addr
, 0, 0, &offset
, &count
, ViewShare
, 0, PAGE_READWRITE
);
1760 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1762 #if defined(__x86_64__) || defined(__i386__)
1763 *(unsigned char*)addr
= 0xc3; /* lret ... in both i386 and x86_64 */
1764 #elif defined(__arm__)
1765 *(unsigned long*)addr
= 0xe12fff1e; /* bx lr */
1766 #elif defined(__aarch64__)
1767 *(unsigned long*)addr
= 0xd65f03c0; /* ret */
1769 ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
1771 trace("trying to execute code in the readwrite only mapped anon file...\n");
1773 trace("...done.\n");
1775 status
= pNtQueryVirtualMemory( GetCurrentProcess(), addr
, MemoryBasicInformation
, &info
, sizeof(info
), &retlen
);
1776 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1777 ok( retlen
== sizeof(info
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1778 ok((info
.Protect
& ~PAGE_NOCACHE
) == PAGE_READWRITE
, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info
.Protect
);
1780 status
= pNtUnmapViewOfSection( GetCurrentProcess(), (char *)addr
+ 0x1050 );
1781 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1785 pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &oldflags
, sizeof(oldflags
) );
1788 static void test_queryvirtualmemory(void)
1792 static const char teststring
[] = "test string";
1793 static char datatestbuf
[42] = "abc";
1794 static char rwtestbuf
[42];
1795 MEMORY_BASIC_INFORMATION mbi
;
1799 module
= GetModuleHandleA( "ntdll.dll" );
1800 trace("Check flags of the PE header of NTDLL.DLL at %p\n", module
);
1801 status
= pNtQueryVirtualMemory(NtCurrentProcess(), module
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1802 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1803 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1804 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1805 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1806 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1807 ok (mbi
.Protect
== PAGE_READONLY
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_READONLY
);
1808 ok (mbi
.Type
== MEM_IMAGE
, "mbi.Type is 0x%x, expected 0x%x\n", mbi
.Type
, MEM_IMAGE
);
1810 trace("Check flags of a function entry in NTDLL.DLL at %p\n", pNtQueryVirtualMemory
);
1811 module
= GetModuleHandleA( "ntdll.dll" );
1812 status
= pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1813 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1814 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1815 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1816 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1817 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1818 ok (mbi
.Protect
== PAGE_EXECUTE_READ
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_EXECUTE_READ
);
1820 trace("Check flags of heap at %p\n", GetProcessHeap());
1821 status
= pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1822 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1823 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1824 ok (mbi
.AllocationProtect
== PAGE_READWRITE
|| mbi
.AllocationProtect
== PAGE_EXECUTE_READWRITE
,
1825 "mbi.AllocationProtect is 0x%x\n", mbi
.AllocationProtect
);
1826 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1827 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_EXECUTE_READWRITE
,
1828 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1830 trace("Check flags of stack at %p\n", stackbuf
);
1831 status
= pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1832 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1833 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1834 ok (mbi
.AllocationProtect
== PAGE_READWRITE
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_READWRITE
);
1835 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1836 ok (mbi
.Protect
== PAGE_READWRITE
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_READWRITE
);
1838 trace("Check flags of read-only data at %p\n", teststring
);
1839 module
= GetModuleHandleA( NULL
);
1840 status
= pNtQueryVirtualMemory(NtCurrentProcess(), teststring
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1841 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1842 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1843 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1844 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1845 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1846 if (mbi
.Protect
!= PAGE_READONLY
)
1847 todo_wine
ok( mbi
.Protect
== PAGE_READONLY
, "mbi.Protect is 0x%x, expected 0x%X\n", mbi
.Protect
, PAGE_READONLY
);
1849 trace("Check flags of read-write data at %p\n", datatestbuf
);
1850 status
= pNtQueryVirtualMemory(NtCurrentProcess(), datatestbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1851 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1852 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1853 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1854 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1855 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1856 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_WRITECOPY
,
1857 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1859 trace("Check flags of read-write uninitialized data (.bss) at %p\n", rwtestbuf
);
1860 status
= pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1861 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1862 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1863 if (mbi
.AllocationBase
== module
)
1865 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1866 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1867 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_WRITECOPY
,
1868 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1870 else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
1873 static void test_affinity(void)
1876 PROCESS_BASIC_INFORMATION pbi
;
1877 DWORD_PTR proc_affinity
, thread_affinity
;
1878 THREAD_BASIC_INFORMATION tbi
;
1882 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1883 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1884 proc_affinity
= pbi
.AffinityMask
;
1885 ok( proc_affinity
== (1 << si
.dwNumberOfProcessors
) - 1, "Unexpected process affinity\n" );
1886 proc_affinity
= 1 << si
.dwNumberOfProcessors
;
1887 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1888 ok( status
== STATUS_INVALID_PARAMETER
,
1889 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1892 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1893 ok( status
== STATUS_INVALID_PARAMETER
,
1894 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1896 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1897 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1898 ok( tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1, "Unexpected thread affinity\n" );
1899 thread_affinity
= 1 << si
.dwNumberOfProcessors
;
1900 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1901 ok( status
== STATUS_INVALID_PARAMETER
,
1902 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1903 thread_affinity
= 0;
1904 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1905 ok( status
== STATUS_INVALID_PARAMETER
,
1906 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1908 thread_affinity
= 1;
1909 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1910 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1911 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1912 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1913 ok( tbi
.AffinityMask
== 1, "Unexpected thread affinity\n" );
1915 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
1916 thread_affinity
= ~(DWORD_PTR
)0;
1917 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1918 ok( broken(status
== STATUS_INVALID_PARAMETER
) || status
== STATUS_SUCCESS
,
1919 "Expected STATUS_SUCCESS, got %08x\n", status
);
1921 if (si
.dwNumberOfProcessors
<= 1)
1923 skip("only one processor, skipping affinity testing\n");
1927 /* Test thread affinity mask resulting from "all processors" flag */
1928 if (status
== STATUS_SUCCESS
)
1930 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1931 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1932 ok( broken(tbi
.AffinityMask
== 1) || tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1,
1933 "Unexpected thread affinity\n" );
1936 skip("Cannot test thread affinity mask for 'all processors' flag\n");
1939 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1940 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1941 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1942 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1943 proc_affinity
= pbi
.AffinityMask
;
1944 ok( proc_affinity
== 2, "Unexpected process affinity\n" );
1945 /* Setting the process affinity changes the thread affinity to match */
1946 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1947 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1948 ok( tbi
.AffinityMask
== 2, "Unexpected thread affinity\n" );
1949 /* The thread affinity is restricted to the process affinity */
1950 thread_affinity
= 1;
1951 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1952 ok( status
== STATUS_INVALID_PARAMETER
,
1953 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1955 proc_affinity
= (1 << si
.dwNumberOfProcessors
) - 1;
1956 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1957 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1958 /* Resetting the process affinity also resets the thread affinity */
1959 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1960 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1961 ok( tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1,
1962 "Unexpected thread affinity\n" );
1965 static void test_NtGetCurrentProcessorNumber(void)
1969 PROCESS_BASIC_INFORMATION pbi
;
1970 THREAD_BASIC_INFORMATION tbi
;
1971 DWORD_PTR old_process_mask
;
1972 DWORD_PTR old_thread_mask
;
1977 if (!pNtGetCurrentProcessorNumber
) {
1978 win_skip("NtGetCurrentProcessorNumber not available\n");
1983 current_cpu
= pNtGetCurrentProcessorNumber();
1984 trace("dwNumberOfProcessors: %d, current processor: %d\n", si
.dwNumberOfProcessors
, current_cpu
);
1986 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1987 old_process_mask
= pbi
.AffinityMask
;
1988 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1990 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1991 old_thread_mask
= tbi
.AffinityMask
;
1992 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1994 /* allow the test to run on all processors */
1995 new_mask
= (1 << si
.dwNumberOfProcessors
) - 1;
1996 status
= pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask
, &new_mask
, sizeof(new_mask
));
1997 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1999 for (i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
2002 status
= pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask
, &new_mask
, sizeof(new_mask
));
2003 ok(status
== STATUS_SUCCESS
, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i
, status
);
2005 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
2006 ok(status
== STATUS_SUCCESS
, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i
, status
);
2008 current_cpu
= pNtGetCurrentProcessorNumber();
2009 ok((current_cpu
== i
), "%d (new_mask 0x%lx): running on processor %d (AffinityMask: 0x%lx)\n",
2010 i
, new_mask
, current_cpu
, tbi
.AffinityMask
);
2013 /* restore old values */
2014 status
= pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask
, &old_process_mask
, sizeof(old_process_mask
));
2015 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
2017 status
= pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask
, &old_thread_mask
, sizeof(old_thread_mask
));
2018 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
2021 static DWORD WINAPI
start_address_thread(void *arg
)
2023 PRTL_THREAD_START_ROUTINE entry
;
2029 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
2030 &entry
, sizeof(entry
), &ret
);
2031 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
2032 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
2033 ok(entry
== (void *)start_address_thread
, "expected %p, got %p\n", start_address_thread
, entry
);
2037 static void test_thread_start_address(void)
2039 PRTL_THREAD_START_ROUTINE entry
, expected_entry
;
2040 IMAGE_NT_HEADERS
*nt
;
2046 module
= GetModuleHandleA(0);
2047 ok(module
!= NULL
, "expected non-NULL address for module\n");
2048 nt
= RtlImageNtHeader(module
);
2049 ok(nt
!= NULL
, "expected non-NULL address for NT header\n");
2053 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
2054 &entry
, sizeof(entry
), &ret
);
2055 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
2056 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
2057 expected_entry
= (void *)((char *)module
+ nt
->OptionalHeader
.AddressOfEntryPoint
);
2058 ok(entry
== expected_entry
, "expected %p, got %p\n", expected_entry
, entry
);
2060 entry
= (void *)0xdeadbeef;
2061 status
= pNtSetInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
2062 &entry
, sizeof(entry
));
2063 ok(status
== STATUS_SUCCESS
|| status
== STATUS_INVALID_PARAMETER
, /* >= Vista */
2064 "expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER, got %08x\n", status
);
2066 if (status
== STATUS_SUCCESS
)
2070 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
2071 &entry
, sizeof(entry
), &ret
);
2072 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
2073 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
2074 ok(entry
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", entry
);
2077 thread
= CreateThread(NULL
, 0, start_address_thread
, NULL
, 0, NULL
);
2078 ok(thread
!= INVALID_HANDLE_VALUE
, "CreateThread failed with %d\n", GetLastError());
2079 ret
= WaitForSingleObject(thread
, 1000);
2080 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
2081 CloseHandle(thread
);
2084 static void test_query_data_alignment(void)
2091 status
= pNtQuerySystemInformation(SystemRecommendedSharedDataAlignment
, &value
, sizeof(value
), &ReturnLength
);
2092 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
2093 ok(sizeof(value
) == ReturnLength
, "Inconsistent length %u\n", ReturnLength
);
2094 ok(value
== 64, "Expected 64, got %u\n", value
);
2102 if(!InitFunctionPtrs())
2105 argc
= winetest_get_mainargs(&argv
);
2106 if (argc
>= 3) return; /* Child */
2108 /* NtQuerySystemInformation */
2110 /* 0x0 SystemBasicInformation */
2111 trace("Starting test_query_basic()\n");
2114 /* 0x1 SystemCpuInformation */
2115 trace("Starting test_query_cpu()\n");
2118 /* 0x2 SystemPerformanceInformation */
2119 trace("Starting test_query_performance()\n");
2120 test_query_performance();
2122 /* 0x3 SystemTimeOfDayInformation */
2123 trace("Starting test_query_timeofday()\n");
2124 test_query_timeofday();
2126 /* 0x5 SystemProcessInformation */
2127 trace("Starting test_query_process()\n");
2128 test_query_process();
2130 /* 0x8 SystemProcessorPerformanceInformation */
2131 trace("Starting test_query_procperf()\n");
2132 test_query_procperf();
2134 /* 0xb SystemModuleInformation */
2135 trace("Starting test_query_module()\n");
2136 test_query_module();
2138 /* 0x10 SystemHandleInformation */
2139 trace("Starting test_query_handle()\n");
2140 test_query_handle();
2142 /* 0x15 SystemCacheInformation */
2143 trace("Starting test_query_cache()\n");
2146 /* 0x17 SystemInterruptInformation */
2147 trace("Starting test_query_interrupt()\n");
2148 test_query_interrupt();
2150 /* 0x23 SystemKernelDebuggerInformation */
2151 trace("Starting test_query_kerndebug()\n");
2152 test_query_kerndebug();
2154 /* 0x25 SystemRegistryQuotaInformation */
2155 trace("Starting test_query_regquota()\n");
2156 test_query_regquota();
2158 /* 0x49 SystemLogicalProcessorInformation */
2159 trace("Starting test_query_logicalproc()\n");
2160 test_query_logicalproc();
2161 test_query_logicalprocex();
2163 /* NtPowerInformation */
2165 /* 0xb ProcessorInformation */
2166 trace("Starting test_query_processor_power_info()\n");
2167 test_query_processor_power_info();
2169 /* NtQueryInformationProcess */
2171 /* 0x0 ProcessBasicInformation */
2172 trace("Starting test_query_process_basic()\n");
2173 test_query_process_basic();
2175 /* 0x2 ProcessIoCounters */
2176 trace("Starting test_query_process_io()\n");
2177 test_query_process_io();
2179 /* 0x3 ProcessVmCounters */
2180 trace("Starting test_query_process_vm()\n");
2181 test_query_process_vm();
2183 /* 0x4 ProcessTimes */
2184 trace("Starting test_query_process_times()\n");
2185 test_query_process_times();
2187 /* 0x7 ProcessDebugPort */
2188 trace("Starting test_process_debug_port()\n");
2189 test_query_process_debug_port(argc
, argv
);
2191 /* 0x14 ProcessHandleCount */
2192 trace("Starting test_query_process_handlecount()\n");
2193 test_query_process_handlecount();
2195 /* 0x1A ProcessWow64Information */
2196 trace("Starting test_query_process_wow64()\n");
2197 test_query_process_wow64();
2199 /* 0x1B ProcessImageFileName */
2200 trace("Starting test_query_process_image_file_name()\n");
2201 test_query_process_image_file_name();
2203 /* 0x1E ProcessDebugObjectHandle */
2204 trace("Starting test_query_process_debug_object_handle()\n");
2205 test_query_process_debug_object_handle(argc
, argv
);
2207 /* 0x1F ProcessDebugFlags */
2208 trace("Starting test_process_debug_flags()\n");
2209 test_query_process_debug_flags(argc
, argv
);
2211 /* belongs to its own file */
2212 trace("Starting test_readvirtualmemory()\n");
2213 test_readvirtualmemory();
2215 trace("Starting test_queryvirtualmemory()\n");
2216 test_queryvirtualmemory();
2218 trace("Starting test_mapprotection()\n");
2219 test_mapprotection();
2221 trace("Starting test_affinity()\n");
2224 trace("Starting test_NtGetCurrentProcessorNumber()\n");
2225 test_NtGetCurrentProcessorNumber();
2227 trace("Starting test_thread_start_address()\n");
2228 test_thread_start_address();
2230 trace("Starting test_query_data_alignment()\n");
2231 test_query_data_alignment();