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
* pNtPowerInformation
)(POWER_INFORMATION_LEVEL
, PVOID
, ULONG
, PVOID
, ULONG
);
27 static NTSTATUS (WINAPI
* pNtQueryInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
, PULONG
);
28 static NTSTATUS (WINAPI
* pNtQueryInformationThread
)(HANDLE
, THREADINFOCLASS
, PVOID
, ULONG
, PULONG
);
29 static NTSTATUS (WINAPI
* pNtSetInformationProcess
)(HANDLE
, PROCESSINFOCLASS
, PVOID
, ULONG
);
30 static NTSTATUS (WINAPI
* pNtSetInformationThread
)(HANDLE
, THREADINFOCLASS
, PVOID
, ULONG
);
31 static NTSTATUS (WINAPI
* pNtReadVirtualMemory
)(HANDLE
, const void*, void*, SIZE_T
, SIZE_T
*);
32 static NTSTATUS (WINAPI
* pNtQueryVirtualMemory
)(HANDLE
, LPCVOID
, MEMORY_INFORMATION_CLASS
, PVOID
, SIZE_T
, SIZE_T
*);
33 static NTSTATUS (WINAPI
* pNtCreateSection
)(HANDLE
*,ACCESS_MASK
,const OBJECT_ATTRIBUTES
*,const LARGE_INTEGER
*,ULONG
,ULONG
,HANDLE
);
34 static NTSTATUS (WINAPI
* pNtMapViewOfSection
)(HANDLE
,HANDLE
,PVOID
*,ULONG
,SIZE_T
,const LARGE_INTEGER
*,SIZE_T
*,SECTION_INHERIT
,ULONG
,ULONG
);
35 static NTSTATUS (WINAPI
* pNtUnmapViewOfSection
)(HANDLE
,PVOID
);
36 static NTSTATUS (WINAPI
* pNtClose
)(HANDLE
);
37 static ULONG (WINAPI
* pNtGetCurrentProcessorNumber
)(void);
38 static BOOL (WINAPI
* pIsWow64Process
)(HANDLE
, PBOOL
);
42 /* one_before_last_pid is used to be able to compare values of a still running process
43 with the output of the test_query_process_times and test_query_process_handlecount tests.
45 static DWORD one_before_last_pid
= 0;
47 #define NTDLL_GET_PROC(func) do { \
48 p ## func = (void*)GetProcAddress(hntdll, #func); \
50 trace("GetProcAddress(%s) failed\n", #func); \
55 static BOOL
InitFunctionPtrs(void)
57 /* All needed functions are NT based, so using GetModuleHandle is a good check */
58 HMODULE hntdll
= GetModuleHandleA("ntdll");
61 win_skip("Not running on NT\n");
65 NTDLL_GET_PROC(NtQuerySystemInformation
);
66 NTDLL_GET_PROC(NtPowerInformation
);
67 NTDLL_GET_PROC(NtQueryInformationProcess
);
68 NTDLL_GET_PROC(NtQueryInformationThread
);
69 NTDLL_GET_PROC(NtSetInformationProcess
);
70 NTDLL_GET_PROC(NtSetInformationThread
);
71 NTDLL_GET_PROC(NtReadVirtualMemory
);
72 NTDLL_GET_PROC(NtQueryVirtualMemory
);
73 NTDLL_GET_PROC(NtClose
);
74 NTDLL_GET_PROC(NtCreateSection
);
75 NTDLL_GET_PROC(NtMapViewOfSection
);
76 NTDLL_GET_PROC(NtUnmapViewOfSection
);
78 /* not present before XP */
79 pNtGetCurrentProcessorNumber
= (void *) GetProcAddress(hntdll
, "NtGetCurrentProcessorNumber");
81 pIsWow64Process
= (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
82 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
86 static void test_query_basic(void)
90 SYSTEM_BASIC_INFORMATION sbi
;
92 /* This test also covers some basic parameter testing that should be the same for
93 * every information class
96 /* Use a nonexistent info class */
97 trace("Check nonexistent info class\n");
98 status
= pNtQuerySystemInformation(-1, NULL
, 0, NULL
);
99 ok( status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
/* vista */,
100 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status
);
102 /* Use an existing class but with a zero-length buffer */
103 trace("Check zero-length buffer\n");
104 status
= pNtQuerySystemInformation(SystemBasicInformation
, NULL
, 0, NULL
);
105 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
107 /* Use an existing class, correct length but no SystemInformation buffer */
108 trace("Check no SystemInformation buffer\n");
109 status
= pNtQuerySystemInformation(SystemBasicInformation
, NULL
, sizeof(sbi
), NULL
);
110 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
/* vista */,
111 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status
);
113 /* Use an existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
114 trace("Check no ReturnLength pointer\n");
115 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), NULL
);
116 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
118 /* Check a too large buffer size */
119 trace("Check a too large buffer size\n");
120 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
) * 2, &ReturnLength
);
121 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
123 /* Finally some correct calls */
124 trace("Check with correct parameters\n");
125 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
126 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
127 ok( sizeof(sbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
129 /* Check if we have some return values */
130 trace("Number of Processors : %d\n", sbi
.NumberOfProcessors
);
131 ok( sbi
.NumberOfProcessors
> 0, "Expected more than 0 processors, got %d\n", sbi
.NumberOfProcessors
);
134 static void test_query_cpu(void)
138 SYSTEM_CPU_INFORMATION sci
;
140 status
= pNtQuerySystemInformation(SystemCpuInformation
, &sci
, sizeof(sci
), &ReturnLength
);
141 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
142 ok( sizeof(sci
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
144 /* Check if we have some return values */
145 trace("Processor FeatureSet : %08x\n", sci
.FeatureSet
);
146 ok( sci
.FeatureSet
!= 0, "Expected some features for this processor, got %08x\n", sci
.FeatureSet
);
149 static void test_query_performance(void)
153 ULONGLONG buffer
[sizeof(SYSTEM_PERFORMANCE_INFORMATION
)/sizeof(ULONGLONG
) + 5];
154 DWORD size
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
156 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, 0, &ReturnLength
);
157 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
159 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
, &ReturnLength
);
160 if (status
== STATUS_INFO_LENGTH_MISMATCH
&& is_wow64
)
162 /* size is larger on wow64 under w2k8/win7 */
164 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
, &ReturnLength
);
166 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
167 ok( ReturnLength
== size
, "Inconsistent length %d\n", ReturnLength
);
169 status
= pNtQuerySystemInformation(SystemPerformanceInformation
, buffer
, size
+ 2, &ReturnLength
);
170 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
171 ok( ReturnLength
== size
|| ReturnLength
== size
+ 2,
172 "Inconsistent length %d\n", ReturnLength
);
174 /* Not return values yet, as struct members are unknown */
177 static void test_query_timeofday(void)
182 /* Copy of our winternl.h structure turned into a private one */
183 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE
{
184 LARGE_INTEGER liKeBootTime
;
185 LARGE_INTEGER liKeSystemTime
;
186 LARGE_INTEGER liExpTimeZoneBias
;
187 ULONG uCurrentTimeZoneId
;
189 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE
;
191 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti
;
193 /* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
195 * Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
196 * then 48 and 0 otherwise
197 * Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
200 * Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
201 * NT only fills the buffer if the return code is STATUS_SUCCESS
205 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, sizeof(sti
), &ReturnLength
);
207 if (status
== STATUS_INFO_LENGTH_MISMATCH
)
209 trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
211 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 0, &ReturnLength
);
212 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
213 ok( 0 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
215 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
216 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 28, &ReturnLength
);
217 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_INFO_LENGTH_MISMATCH
/* NT4 */), "Expected STATUS_SUCCESS, got %08x\n", status
);
218 ok( 0xdeadbeef == sti
.uCurrentTimeZoneId
, "This part of the buffer should not have been filled\n");
220 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 32, &ReturnLength
);
221 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
222 ok( 32 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
226 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 0, &ReturnLength
);
227 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
228 ok( 0 == ReturnLength
, "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
230 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
231 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 24, &ReturnLength
);
232 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
233 ok( 24 == ReturnLength
, "ReturnLength should be 24, it is (%d)\n", ReturnLength
);
234 ok( 0xdeadbeef == sti
.uCurrentTimeZoneId
, "This part of the buffer should not have been filled\n");
236 sti
.uCurrentTimeZoneId
= 0xdeadbeef;
237 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 32, &ReturnLength
);
238 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
239 ok( 32 == ReturnLength
, "ReturnLength should be 32, it is (%d)\n", ReturnLength
);
240 ok( 0xdeadbeef != sti
.uCurrentTimeZoneId
, "Buffer should have been partially filled\n");
242 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, 49, &ReturnLength
);
243 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
244 ok( ReturnLength
== 0 || ReturnLength
== sizeof(sti
) /* vista */,
245 "ReturnLength should be 0, it is (%d)\n", ReturnLength
);
247 status
= pNtQuerySystemInformation(SystemTimeOfDayInformation
, &sti
, sizeof(sti
), &ReturnLength
);
248 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
249 ok( sizeof(sti
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
252 /* Check if we have some return values */
253 trace("uCurrentTimeZoneId : (%d)\n", sti
.uCurrentTimeZoneId
);
256 static void test_query_process(void)
263 SYSTEM_BASIC_INFORMATION sbi
;
265 /* Copy of our winternl.h structure turned into a private one */
266 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE
{
267 ULONG NextEntryOffset
;
270 FILETIME ftCreationTime
;
272 FILETIME ftKernelTime
;
273 UNICODE_STRING ProcessName
;
274 DWORD dwBasePriority
;
275 HANDLE UniqueProcessId
;
276 HANDLE ParentProcessId
;
280 VM_COUNTERS vmCounters
;
281 IO_COUNTERS ioCounters
;
282 SYSTEM_THREAD_INFORMATION ti
[1];
283 } SYSTEM_PROCESS_INFORMATION_PRIVATE
;
285 ULONG SystemInformationLength
= sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE
);
286 SYSTEM_PROCESS_INFORMATION_PRIVATE
*spi
, *spi_buf
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
288 /* test ReturnLength */
290 status
= pNtQuerySystemInformation(SystemProcessInformation
, NULL
, 0, &ReturnLength
);
291 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH got %08x\n", status
);
292 ok( ReturnLength
> 0 || broken(ReturnLength
== 0) /* NT4, Win2K */,
293 "Expected a ReturnLength to show the needed length\n");
295 /* W2K3 and later returns the needed length, the rest returns 0, so we have to loop */
298 status
= pNtQuerySystemInformation(SystemProcessInformation
, spi_buf
, SystemInformationLength
, &ReturnLength
);
300 if (status
!= STATUS_INFO_LENGTH_MISMATCH
) break;
302 spi_buf
= HeapReAlloc(GetProcessHeap(), 0, spi_buf
, SystemInformationLength
*= 2);
304 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
307 /* Get the first NextEntryOffset, from this we can deduce the OS version we're running
310 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
312 * NextEntryOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
313 * Wine (with every windows version):
314 * NextEntryOffset for a process is 0 if just this test is running
315 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
316 * ProcessName.MaximumLength
317 * if more wine processes are running
319 * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
322 pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
324 is_nt
= ( spi
->NextEntryOffset
- (sbi
.NumberOfProcessors
* sizeof(SYSTEM_THREAD_INFORMATION
)) == 136);
326 if (is_nt
) win_skip("Windows version is NT, we will skip thread tests\n");
328 /* Check if we have some return values
330 * On windows there will be several processes running (Including the always present Idle and System)
331 * On wine we only have one (if this test is the only wine process running)
334 /* Loop through the processes */
340 last_pid
= (DWORD_PTR
)spi
->UniqueProcessId
;
342 ok( spi
->dwThreadCount
> 0, "Expected some threads for this process, got 0\n");
344 /* Loop through the threads, skip NT4 for now */
349 for ( j
= 0; j
< spi
->dwThreadCount
; j
++)
352 ok ( spi
->ti
[j
].ClientId
.UniqueProcess
== spi
->UniqueProcessId
,
353 "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
354 spi
->ti
[j
].ClientId
.UniqueProcess
, spi
->UniqueProcessId
);
358 if (!spi
->NextEntryOffset
) break;
360 one_before_last_pid
= last_pid
;
362 spi
= (SYSTEM_PROCESS_INFORMATION_PRIVATE
*)((char*)spi
+ spi
->NextEntryOffset
);
364 trace("Total number of running processes : %d\n", i
);
365 if (!is_nt
) trace("Total number of running threads : %d\n", k
);
367 if (one_before_last_pid
== 0) one_before_last_pid
= last_pid
;
369 HeapFree( GetProcessHeap(), 0, spi_buf
);
372 static void test_query_procperf(void)
377 SYSTEM_BASIC_INFORMATION sbi
;
378 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
* sppi
;
380 /* Find out the number of processors */
381 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
382 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
383 NeededLength
= sbi
.NumberOfProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
385 sppi
= HeapAlloc(GetProcessHeap(), 0, NeededLength
);
387 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, 0, &ReturnLength
);
388 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
390 /* Try it for 1 processor */
391 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
392 sppi
->UserTime
.QuadPart
= 0xdeaddead;
393 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
394 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
,
395 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
), &ReturnLength
);
396 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
397 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) == ReturnLength
,
398 "Inconsistent length %d\n", ReturnLength
);
399 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
400 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
401 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
403 /* Try it for all processors */
404 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
405 sppi
->UserTime
.QuadPart
= 0xdeaddead;
406 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
407 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, NeededLength
, &ReturnLength
);
408 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
409 ok( NeededLength
== ReturnLength
, "Inconsistent length (%d) <-> (%d)\n", NeededLength
, ReturnLength
);
410 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
411 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
412 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
414 /* A too large given buffer size */
415 sppi
= HeapReAlloc(GetProcessHeap(), 0, sppi
, NeededLength
+ 2);
416 sppi
->KernelTime
.QuadPart
= 0xdeaddead;
417 sppi
->UserTime
.QuadPart
= 0xdeaddead;
418 sppi
->IdleTime
.QuadPart
= 0xdeaddead;
419 status
= pNtQuerySystemInformation(SystemProcessorPerformanceInformation
, sppi
, NeededLength
+ 2, &ReturnLength
);
420 ok( status
== STATUS_SUCCESS
|| status
== STATUS_INFO_LENGTH_MISMATCH
/* vista */,
421 "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
422 ok( NeededLength
== ReturnLength
, "Inconsistent length (%d) <-> (%d)\n", NeededLength
, ReturnLength
);
423 if (status
== STATUS_SUCCESS
)
425 ok (sppi
->KernelTime
.QuadPart
!= 0xdeaddead, "KernelTime unchanged\n");
426 ok (sppi
->UserTime
.QuadPart
!= 0xdeaddead, "UserTime unchanged\n");
427 ok (sppi
->IdleTime
.QuadPart
!= 0xdeaddead, "IdleTime unchanged\n");
429 else /* vista and 2008 */
431 ok (sppi
->KernelTime
.QuadPart
== 0xdeaddead, "KernelTime changed\n");
432 ok (sppi
->UserTime
.QuadPart
== 0xdeaddead, "UserTime changed\n");
433 ok (sppi
->IdleTime
.QuadPart
== 0xdeaddead, "IdleTime changed\n");
436 HeapFree( GetProcessHeap(), 0, sppi
);
439 static void test_query_module(void)
443 ULONG ModuleCount
, i
;
445 ULONG SystemInformationLength
= sizeof(SYSTEM_MODULE_INFORMATION
);
446 SYSTEM_MODULE_INFORMATION
* smi
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
449 /* Request the needed length */
450 status
= pNtQuerySystemInformation(SystemModuleInformation
, smi
, 0, &ReturnLength
);
451 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
452 ok( ReturnLength
> 0, "Expected a ReturnLength to show the needed length\n");
454 SystemInformationLength
= ReturnLength
;
455 smi
= HeapReAlloc(GetProcessHeap(), 0, smi
, SystemInformationLength
);
456 status
= pNtQuerySystemInformation(SystemModuleInformation
, smi
, SystemInformationLength
, &ReturnLength
);
457 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
459 ModuleCount
= smi
->ModulesCount
;
460 sm
= &smi
->Modules
[0];
461 /* our implementation is a stub for now */
462 ok( ModuleCount
> 0, "Expected some modules to be loaded\n");
464 /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
465 for (i
= 0; i
< ModuleCount
; i
++)
467 ok( i
== sm
->Id
, "Id (%d) should have matched %u\n", sm
->Id
, i
);
471 HeapFree( GetProcessHeap(), 0, smi
);
474 static void test_query_handle(void)
478 ULONG SystemInformationLength
= sizeof(SYSTEM_HANDLE_INFORMATION
);
479 SYSTEM_HANDLE_INFORMATION
* shi
= HeapAlloc(GetProcessHeap(), 0, SystemInformationLength
);
481 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
482 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
483 todo_wine
ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
485 SystemInformationLength
= ReturnLength
;
486 shi
= HeapReAlloc(GetProcessHeap(), 0, shi
, SystemInformationLength
);
487 status
= pNtQuerySystemInformation(SystemHandleInformation
, shi
, SystemInformationLength
, &ReturnLength
);
488 if (status
!= STATUS_INFO_LENGTH_MISMATCH
) /* vista */
490 ok( status
== STATUS_SUCCESS
,
491 "Expected STATUS_SUCCESS, got %08x\n", status
);
493 /* Check if we have some return values */
494 trace("Number of Handles : %d\n", shi
->Count
);
497 /* our implementation is a stub for now */
498 ok( shi
->Count
> 1, "Expected more than 1 handles, got (%d)\n", shi
->Count
);
501 HeapFree( GetProcessHeap(), 0, shi
);
504 static void test_query_cache(void)
509 SYSTEM_CACHE_INFORMATION
*sci
= (SYSTEM_CACHE_INFORMATION
*) buffer
;
513 /* the large SYSTEM_CACHE_INFORMATION on WIN64 is not documented */
514 expected
= sizeof(SYSTEM_CACHE_INFORMATION
);
515 for (i
= sizeof(buffer
); i
>= expected
; i
--)
517 ReturnLength
= 0xdeadbeef;
518 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
519 ok(!status
&& (ReturnLength
== expected
),
520 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i
, status
, ReturnLength
, expected
);
523 /* buffer too small for the full result.
524 Up to win7, the function succeeds with a partial result. */
525 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
528 expected
= offsetof(SYSTEM_CACHE_INFORMATION
, MinimumWorkingSet
);
529 for (; i
>= expected
; i
--)
531 ReturnLength
= 0xdeadbeef;
532 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
533 ok(!status
&& (ReturnLength
== expected
),
534 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i
, status
, ReturnLength
, expected
);
538 /* buffer too small for the result, this call will always fail */
539 ReturnLength
= 0xdeadbeef;
540 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, i
, &ReturnLength
);
541 ok( status
== STATUS_INFO_LENGTH_MISMATCH
&&
542 ((ReturnLength
== expected
) || broken(!ReturnLength
) || broken(ReturnLength
== 0xfffffff0)),
543 "%d: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", i
, status
, ReturnLength
, expected
);
546 /* this crashes on some vista / win7 machines */
547 ReturnLength
= 0xdeadbeef;
548 status
= pNtQuerySystemInformation(SystemCacheInformation
, sci
, 0, &ReturnLength
);
549 ok( status
== STATUS_INFO_LENGTH_MISMATCH
&&
550 ((ReturnLength
== expected
) || broken(!ReturnLength
) || broken(ReturnLength
== 0xfffffff0)),
551 "0: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", status
, ReturnLength
, expected
);
555 static void test_query_interrupt(void)
560 SYSTEM_BASIC_INFORMATION sbi
;
561 SYSTEM_INTERRUPT_INFORMATION
* sii
;
563 /* Find out the number of processors */
564 status
= pNtQuerySystemInformation(SystemBasicInformation
, &sbi
, sizeof(sbi
), &ReturnLength
);
565 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
566 NeededLength
= sbi
.NumberOfProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
);
568 sii
= HeapAlloc(GetProcessHeap(), 0, NeededLength
);
570 status
= pNtQuerySystemInformation(SystemInterruptInformation
, sii
, 0, &ReturnLength
);
571 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
573 /* Try it for all processors */
574 status
= pNtQuerySystemInformation(SystemInterruptInformation
, sii
, NeededLength
, &ReturnLength
);
575 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
577 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
578 * No test added for this as it's highly unlikely that an app depends on this
581 HeapFree( GetProcessHeap(), 0, sii
);
584 static void test_query_kerndebug(void)
588 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
;
590 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, 0, &ReturnLength
);
591 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
593 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, sizeof(skdi
), &ReturnLength
);
594 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
595 ok( sizeof(skdi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
597 status
= pNtQuerySystemInformation(SystemKernelDebuggerInformation
, &skdi
, sizeof(skdi
) + 2, &ReturnLength
);
598 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
599 ok( sizeof(skdi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
602 static void test_query_regquota(void)
606 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi
;
608 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, 0, &ReturnLength
);
609 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
611 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, sizeof(srqi
), &ReturnLength
);
612 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
613 ok( sizeof(srqi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
615 status
= pNtQuerySystemInformation(SystemRegistryQuotaInformation
, &srqi
, sizeof(srqi
) + 2, &ReturnLength
);
616 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
617 ok( sizeof(srqi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
620 static void test_query_logicalproc(void)
623 ULONG len
, i
, proc_no
;
624 SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*slpi
;
629 status
= pNtQuerySystemInformation(SystemLogicalProcessorInformation
, NULL
, 0, &len
);
630 if(status
== STATUS_INVALID_INFO_CLASS
)
632 win_skip("SystemLogicalProcessorInformation is not supported\n");
635 if(status
== STATUS_NOT_IMPLEMENTED
)
637 todo_wine
ok(0, "SystemLogicalProcessorInformation is not implemented\n");
640 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
641 ok(len
%sizeof(*slpi
) == 0, "Incorrect length %d\n", len
);
643 slpi
= HeapAlloc(GetProcessHeap(), 0, len
);
644 status
= pNtQuerySystemInformation(SystemLogicalProcessorInformation
, slpi
, len
, &len
);
645 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
648 for(i
=0; i
<len
/sizeof(*slpi
); i
++) {
649 switch(slpi
[i
].Relationship
) {
650 case RelationProcessorCore
:
651 /* Get number of logical processors */
652 for(; slpi
[i
].ProcessorMask
; slpi
[i
].ProcessorMask
/= 2)
653 proc_no
+= slpi
[i
].ProcessorMask
%2;
659 ok(proc_no
> 0, "No processors were found\n");
660 if(si
.dwNumberOfProcessors
<= 32)
661 ok(proc_no
== si
.dwNumberOfProcessors
, "Incorrect number of logical processors: %d, expected %d\n",
662 proc_no
, si
.dwNumberOfProcessors
);
664 HeapFree(GetProcessHeap(), 0, slpi
);
667 static void test_query_processor_power_info(void)
670 PROCESSOR_POWER_INFORMATION
* ppi
;
676 size
= si
.dwNumberOfProcessors
* sizeof(PROCESSOR_POWER_INFORMATION
);
677 ppi
= HeapAlloc(GetProcessHeap(), 0, size
);
679 /* If size < (sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors), Win7 returns
680 * STATUS_BUFFER_TOO_SMALL. WinXP returns STATUS_SUCCESS for any value of size. It copies as
681 * many whole PROCESSOR_POWER_INFORMATION structures that there is room for. Even if there is
682 * not enough room for one structure, WinXP still returns STATUS_SUCCESS having done nothing.
684 * If ppi == NULL, Win7 returns STATUS_INVALID_PARAMETER while WinXP returns STATUS_SUCCESS
687 * The same behavior is seen with CallNtPowerInformation (in powrprof.dll).
690 if (si
.dwNumberOfProcessors
> 1)
692 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
693 ppi
[i
].Number
= 0xDEADBEEF;
695 /* Call with a buffer size that is large enough to hold at least one but not large
696 * enough to hold them all. This will be STATUS_SUCCESS on WinXP but not on Win7 */
697 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, size
- sizeof(PROCESSOR_POWER_INFORMATION
));
698 if (status
== STATUS_SUCCESS
)
700 /* lax version found on older Windows like WinXP */
701 ok( (ppi
[si
.dwNumberOfProcessors
- 2].Number
!= 0xDEADBEEF) &&
702 (ppi
[si
.dwNumberOfProcessors
- 1].Number
== 0xDEADBEEF),
703 "Expected all but the last record to be overwritten.\n");
705 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, 0, size
);
706 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
708 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
709 ppi
[i
].Number
= 0xDEADBEEF;
710 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, sizeof(PROCESSOR_POWER_INFORMATION
) - 1);
711 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
712 for(i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
713 if (ppi
[i
].Number
!= 0xDEADBEEF) break;
714 ok( i
== si
.dwNumberOfProcessors
, "Expected untouched buffer\n");
718 /* picky version found on newer Windows like Win7 */
719 ok( ppi
[1].Number
== 0xDEADBEEF, "Expected untouched buffer.\n");
720 ok( status
== STATUS_BUFFER_TOO_SMALL
, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status
);
722 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, 0, size
);
723 ok( status
== STATUS_SUCCESS
|| status
== STATUS_INVALID_PARAMETER
, "Got %08x\n", status
);
725 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, 0);
726 ok( status
== STATUS_BUFFER_TOO_SMALL
|| status
== STATUS_INVALID_PARAMETER
, "Got %08x\n", status
);
731 skip("Test needs more than one processor.\n");
734 status
= pNtPowerInformation(ProcessorInformation
, 0, 0, ppi
, size
);
735 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
737 HeapFree(GetProcessHeap(), 0, ppi
);
740 static void test_query_process_wow64(void)
744 ULONG_PTR pbi
[2], dummy
;
746 memset(&dummy
, 0xcc, sizeof(dummy
));
748 /* Do not give a handle and buffer */
749 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, NULL
, 0, NULL
);
750 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
752 /* Use a correct info class and buffer size, but still no handle and buffer */
753 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, NULL
, sizeof(ULONG_PTR
), NULL
);
754 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
755 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE, got %08x\n", status
);
757 /* Use a correct info class, buffer size and handle, but no buffer */
758 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, NULL
, sizeof(ULONG_PTR
), NULL
);
759 ok( status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
761 /* Use a correct info class, buffer and buffer size, but no handle */
762 pbi
[0] = pbi
[1] = dummy
;
763 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), NULL
);
764 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
765 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
766 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
768 /* Use a greater buffer size */
769 pbi
[0] = pbi
[1] = dummy
;
770 status
= pNtQueryInformationProcess(NULL
, ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) + 1, NULL
);
771 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
772 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
773 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
775 /* Use no ReturnLength */
776 pbi
[0] = pbi
[1] = dummy
;
777 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), NULL
);
778 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
779 trace( "Platform is_wow64 %d, ProcessInformation of ProcessWow64Information %lx\n", is_wow64
, pbi
[0]);
780 ok( is_wow64
== (pbi
[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64
, pbi
[0]);
781 ok( pbi
[0] != dummy
, "pbi[0] %lx\n", pbi
[0]);
782 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
783 /* Test written size on 64 bit by checking high 32 bit buffer */
784 if (sizeof(ULONG_PTR
) > sizeof(DWORD
))
786 DWORD
*ptr
= (DWORD
*)pbi
;
787 ok( ptr
[1] != (DWORD
)dummy
, "ptr[1] unchanged!\n");
790 /* Finally some correct calls */
791 pbi
[0] = pbi
[1] = dummy
;
792 ReturnLength
= 0xdeadbeef;
793 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
), &ReturnLength
);
794 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
795 ok( is_wow64
== (pbi
[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64
, pbi
[0]);
796 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
797 ok( ReturnLength
== sizeof(ULONG_PTR
), "Inconsistent length %d\n", ReturnLength
);
799 /* Everything is correct except a too small buffer size */
800 pbi
[0] = pbi
[1] = dummy
;
801 ReturnLength
= 0xdeadbeef;
802 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) - 1, &ReturnLength
);
803 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
804 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
805 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
806 todo_wine
ok( ReturnLength
== 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength
);
808 /* Everything is correct except a too large buffer size */
809 pbi
[0] = pbi
[1] = dummy
;
810 ReturnLength
= 0xdeadbeef;
811 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information
, pbi
, sizeof(ULONG_PTR
) + 1, &ReturnLength
);
812 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
813 ok( pbi
[0] == dummy
, "pbi[0] changed to %lx\n", pbi
[0]);
814 ok( pbi
[1] == dummy
, "pbi[1] changed to %lx\n", pbi
[1]);
815 todo_wine
ok( ReturnLength
== 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength
);
818 static void test_query_process_basic(void)
823 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE
{
824 DWORD_PTR ExitStatus
;
826 DWORD_PTR AffinityMask
;
827 DWORD_PTR BasePriority
;
828 ULONG_PTR UniqueProcessId
;
829 ULONG_PTR InheritedFromUniqueProcessId
;
830 } PROCESS_BASIC_INFORMATION_PRIVATE
;
832 PROCESS_BASIC_INFORMATION_PRIVATE pbi
;
834 /* This test also covers some basic parameter testing that should be the same for
835 * every information class
838 /* Use a nonexistent info class */
839 trace("Check nonexistent info class\n");
840 status
= pNtQueryInformationProcess(NULL
, -1, NULL
, 0, NULL
);
841 ok( status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
/* vista */,
842 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status
);
844 /* Do not give a handle and buffer */
845 trace("Check NULL handle and buffer and zero-length buffersize\n");
846 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, NULL
, 0, NULL
);
847 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
849 /* Use a correct info class and buffer size, but still no handle and buffer */
850 trace("Check NULL handle and buffer\n");
851 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, NULL
, sizeof(pbi
), NULL
);
852 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
853 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
855 /* Use a correct info class and buffer size, but still no handle */
856 trace("Check NULL handle\n");
857 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
858 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
860 /* Use a greater buffer size */
861 trace("Check NULL handle and too large buffersize\n");
862 status
= pNtQueryInformationProcess(NULL
, ProcessBasicInformation
, &pbi
, sizeof(pbi
) * 2, NULL
);
863 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
865 /* Use no ReturnLength */
866 trace("Check NULL ReturnLength\n");
867 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
868 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
870 /* Finally some correct calls */
871 trace("Check with correct parameters\n");
872 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), &ReturnLength
);
873 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
874 ok( sizeof(pbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
876 /* Everything is correct except a too large buffersize */
877 trace("Too large buffersize\n");
878 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
) * 2, &ReturnLength
);
879 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
880 ok( sizeof(pbi
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
882 /* Check if we have some return values */
883 trace("ProcessID : %lx\n", pbi
.UniqueProcessId
);
884 ok( pbi
.UniqueProcessId
> 0, "Expected a ProcessID > 0, got 0\n");
887 static void test_query_process_vm(void)
892 ULONG old_size
= FIELD_OFFSET(VM_COUNTERS
,PrivatePageCount
);
894 status
= pNtQueryInformationProcess(NULL
, ProcessVmCounters
, NULL
, sizeof(pvi
), NULL
);
895 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
896 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
898 status
= pNtQueryInformationProcess(NULL
, ProcessVmCounters
, &pvi
, old_size
, NULL
);
899 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
901 /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
902 Windows W2K will only report success for 44.
903 For now we only care for 44, which is FIELD_OFFSET(VM_COUNTERS,PrivatePageCount))
906 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, 24, &ReturnLength
);
907 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
909 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, old_size
, &ReturnLength
);
910 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
911 ok( old_size
== ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
913 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &pvi
, 46, &ReturnLength
);
914 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
915 ok( ReturnLength
== old_size
|| ReturnLength
== sizeof(pvi
), "Inconsistent length %d\n", ReturnLength
);
917 /* Check if we have some return values */
918 trace("WorkingSetSize : %ld\n", pvi
.WorkingSetSize
);
921 ok( pvi
.WorkingSetSize
> 0, "Expected a WorkingSetSize > 0\n");
925 static void test_query_process_io(void)
931 /* NT4 doesn't support this information class, so check for it */
932 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
), &ReturnLength
);
933 if (status
== STATUS_NOT_SUPPORTED
)
935 win_skip("ProcessIoCounters information class is not supported\n");
939 status
= pNtQueryInformationProcess(NULL
, ProcessIoCounters
, NULL
, sizeof(pii
), NULL
);
940 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
941 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
943 status
= pNtQueryInformationProcess(NULL
, ProcessIoCounters
, &pii
, sizeof(pii
), NULL
);
944 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
946 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, 24, &ReturnLength
);
947 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
949 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
), &ReturnLength
);
950 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
951 ok( sizeof(pii
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
953 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters
, &pii
, sizeof(pii
) * 2, &ReturnLength
);
954 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
955 ok( sizeof(pii
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
957 /* Check if we have some return values */
958 trace("OtherOperationCount : 0x%x%08x\n", (DWORD
)(pii
.OtherOperationCount
>> 32), (DWORD
)pii
.OtherOperationCount
);
961 ok( pii
.OtherOperationCount
> 0, "Expected an OtherOperationCount > 0\n");
965 static void test_query_process_times(void)
970 SYSTEMTIME UTC
, Local
;
971 KERNEL_USER_TIMES spti
;
973 status
= pNtQueryInformationProcess(NULL
, ProcessTimes
, NULL
, sizeof(spti
), NULL
);
974 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
975 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
977 status
= pNtQueryInformationProcess(NULL
, ProcessTimes
, &spti
, sizeof(spti
), NULL
);
978 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
980 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes
, &spti
, 24, &ReturnLength
);
981 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
983 process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, one_before_last_pid
);
986 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid
, GetLastError());
987 process
= GetCurrentProcess();
988 trace("ProcessTimes for current process\n");
991 trace("ProcessTimes for process with ID : %d\n", one_before_last_pid
);
993 status
= pNtQueryInformationProcess( process
, ProcessTimes
, &spti
, sizeof(spti
), &ReturnLength
);
994 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
995 ok( sizeof(spti
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
996 CloseHandle(process
);
998 FileTimeToSystemTime((const FILETIME
*)&spti
.CreateTime
, &UTC
);
999 SystemTimeToTzSpecificLocalTime(NULL
, &UTC
, &Local
);
1000 trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local
.wMonth
, Local
.wDay
, Local
.wYear
,
1001 Local
.wHour
, Local
.wMinute
, Local
.wSecond
);
1003 FileTimeToSystemTime((const FILETIME
*)&spti
.ExitTime
, &UTC
);
1004 SystemTimeToTzSpecificLocalTime(NULL
, &UTC
, &Local
);
1005 trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local
.wMonth
, Local
.wDay
, Local
.wYear
,
1006 Local
.wHour
, Local
.wMinute
, Local
.wSecond
);
1008 FileTimeToSystemTime((const FILETIME
*)&spti
.KernelTime
, &Local
);
1009 trace("KernelTime : %02d:%02d:%02d.%03d\n", Local
.wHour
, Local
.wMinute
, Local
.wSecond
, Local
.wMilliseconds
);
1011 FileTimeToSystemTime((const FILETIME
*)&spti
.UserTime
, &Local
);
1012 trace("UserTime : %02d:%02d:%02d.%03d\n", Local
.wHour
, Local
.wMinute
, Local
.wSecond
, Local
.wMilliseconds
);
1014 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes
, &spti
, sizeof(spti
) * 2, &ReturnLength
);
1015 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1016 ok( sizeof(spti
) == ReturnLength
||
1017 ReturnLength
== 0 /* vista */ ||
1018 broken(is_wow64
), /* returns garbage on wow64 */
1019 "Inconsistent length %d\n", ReturnLength
);
1022 static void test_query_process_debug_port(int argc
, char **argv
)
1024 DWORD_PTR debug_port
= 0xdeadbeef;
1025 char cmdline
[MAX_PATH
];
1026 PROCESS_INFORMATION pi
;
1027 STARTUPINFOA si
= { 0 };
1031 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1034 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, DEBUG_PROCESS
, NULL
, NULL
, &si
, &pi
);
1035 ok(ret
, "CreateProcess failed, last error %#x.\n", GetLastError());
1038 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1040 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1042 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1043 NULL
, sizeof(debug_port
), NULL
);
1044 ok(status
== STATUS_INVALID_HANDLE
|| status
== STATUS_ACCESS_VIOLATION
,
1045 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1047 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1048 NULL
, sizeof(debug_port
), NULL
);
1049 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status
);
1051 status
= pNtQueryInformationProcess(NULL
, ProcessDebugPort
,
1052 &debug_port
, sizeof(debug_port
), NULL
);
1053 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1055 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1056 &debug_port
, sizeof(debug_port
) - 1, NULL
);
1057 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1059 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1060 &debug_port
, sizeof(debug_port
) + 1, NULL
);
1061 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1063 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort
,
1064 &debug_port
, sizeof(debug_port
), NULL
);
1065 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1066 ok(debug_port
== 0, "Expected port 0, got %#lx.\n", debug_port
);
1068 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugPort
,
1069 &debug_port
, sizeof(debug_port
), NULL
);
1070 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1071 ok(debug_port
== ~(DWORD_PTR
)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR
)0, debug_port
);
1077 ret
= WaitForDebugEvent(&ev
, INFINITE
);
1078 ok(ret
, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1081 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1083 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1084 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1088 ret
= CloseHandle(pi
.hThread
);
1089 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1090 ret
= CloseHandle(pi
.hProcess
);
1091 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1094 static void test_query_process_handlecount(void)
1099 BYTE buffer
[2 * sizeof(DWORD
)];
1102 status
= pNtQueryInformationProcess(NULL
, ProcessHandleCount
, NULL
, sizeof(handlecount
), NULL
);
1103 ok( status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_HANDLE
,
1104 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status
);
1106 status
= pNtQueryInformationProcess(NULL
, ProcessHandleCount
, &handlecount
, sizeof(handlecount
), NULL
);
1107 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1109 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount
, &handlecount
, 2, &ReturnLength
);
1110 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1112 process
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, one_before_last_pid
);
1115 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid
, GetLastError());
1116 process
= GetCurrentProcess();
1117 trace("ProcessHandleCount for current process\n");
1120 trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid
);
1122 status
= pNtQueryInformationProcess( process
, ProcessHandleCount
, &handlecount
, sizeof(handlecount
), &ReturnLength
);
1123 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1124 ok( sizeof(handlecount
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1125 CloseHandle(process
);
1127 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount
, buffer
, sizeof(buffer
), &ReturnLength
);
1128 ok( status
== STATUS_INFO_LENGTH_MISMATCH
|| status
== STATUS_SUCCESS
,
1129 "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08x\n", status
);
1130 ok( sizeof(handlecount
) == ReturnLength
, "Inconsistent length %d\n", ReturnLength
);
1132 /* Check if we have some return values */
1133 trace("HandleCount : %d\n", handlecount
);
1136 ok( handlecount
> 0, "Expected some handles, got 0\n");
1140 static void test_query_process_image_file_name(void)
1144 UNICODE_STRING image_file_name
;
1149 status
= pNtQueryInformationProcess(NULL
, ProcessImageFileName
, &image_file_name
, sizeof(image_file_name
), NULL
);
1150 if (status
== STATUS_INVALID_INFO_CLASS
)
1152 win_skip("ProcessImageFileName is not supported\n");
1155 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1157 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, &image_file_name
, 2, &ReturnLength
);
1158 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1160 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, &image_file_name
, sizeof(image_file_name
), &ReturnLength
);
1161 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status
);
1163 buffer
= HeapAlloc(GetProcessHeap(), 0, ReturnLength
);
1164 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName
, buffer
, ReturnLength
, &ReturnLength
);
1165 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1166 memcpy(&image_file_name
, buffer
, sizeof(image_file_name
));
1167 len
= WideCharToMultiByte(CP_ACP
, 0, image_file_name
.Buffer
, image_file_name
.Length
/sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
1168 file_nameA
= HeapAlloc(GetProcessHeap(), 0, len
+ 1);
1169 WideCharToMultiByte(CP_ACP
, 0, image_file_name
.Buffer
, image_file_name
.Length
/sizeof(WCHAR
), file_nameA
, len
, NULL
, NULL
);
1170 file_nameA
[len
] = '\0';
1171 HeapFree(GetProcessHeap(), 0, buffer
);
1172 trace("process image file name: %s\n", file_nameA
);
1173 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
);
1174 HeapFree(GetProcessHeap(), 0, file_nameA
);
1177 static void test_query_process_debug_object_handle(int argc
, char **argv
)
1179 char cmdline
[MAX_PATH
];
1180 STARTUPINFOA si
= {0};
1181 PROCESS_INFORMATION pi
;
1183 HANDLE debug_object
;
1186 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1189 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, DEBUG_PROCESS
, NULL
,
1191 ok(ret
, "CreateProcess failed with last error %u\n", GetLastError());
1194 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
, NULL
,
1196 if (status
== STATUS_INVALID_INFO_CLASS
|| status
== STATUS_NOT_IMPLEMENTED
)
1198 win_skip("ProcessDebugObjectHandle is not supported\n");
1201 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1202 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n",
1205 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
, NULL
,
1206 sizeof(debug_object
), NULL
);
1207 ok(status
== STATUS_INVALID_HANDLE
||
1208 status
== STATUS_ACCESS_VIOLATION
, /* XP */
1209 "Expected NtQueryInformationProcess to return STATUS_INVALID_HANDLE, got 0x%08x\n", status
);
1211 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1212 ProcessDebugObjectHandle
, NULL
, sizeof(debug_object
), NULL
);
1213 ok(status
== STATUS_ACCESS_VIOLATION
,
1214 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status
);
1216 status
= pNtQueryInformationProcess(NULL
, ProcessDebugObjectHandle
,
1217 &debug_object
, sizeof(debug_object
), NULL
);
1218 ok(status
== STATUS_INVALID_HANDLE
,
1219 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status
);
1221 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1222 ProcessDebugObjectHandle
, &debug_object
,
1223 sizeof(debug_object
) - 1, NULL
);
1224 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1225 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status
);
1227 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1228 ProcessDebugObjectHandle
, &debug_object
,
1229 sizeof(debug_object
) + 1, NULL
);
1230 ok(status
== STATUS_INFO_LENGTH_MISMATCH
,
1231 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status
);
1233 debug_object
= (HANDLE
)0xdeadbeef;
1234 status
= pNtQueryInformationProcess(GetCurrentProcess(),
1235 ProcessDebugObjectHandle
, &debug_object
,
1236 sizeof(debug_object
), NULL
);
1237 ok(status
== STATUS_PORT_NOT_SET
,
1238 "Expected NtQueryInformationProcess to return STATUS_PORT_NOT_SET, got 0x%08x\n", status
);
1239 ok(debug_object
== NULL
||
1240 broken(debug_object
== (HANDLE
)0xdeadbeef), /* Wow64 */
1241 "Expected debug object handle to be NULL, got %p\n", debug_object
);
1243 debug_object
= (HANDLE
)0xdeadbeef;
1244 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugObjectHandle
,
1245 &debug_object
, sizeof(debug_object
), NULL
);
1247 ok(status
== STATUS_SUCCESS
,
1248 "Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status
);
1250 ok(debug_object
!= NULL
,
1251 "Expected debug object handle to be non-NULL, got %p\n", debug_object
);
1257 ret
= WaitForDebugEvent(&ev
, INFINITE
);
1258 ok(ret
, "WaitForDebugEvent failed with last error %u\n", GetLastError());
1261 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1263 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1264 ok(ret
, "ContinueDebugEvent failed with last error %u\n", GetLastError());
1268 ret
= CloseHandle(pi
.hThread
);
1269 ok(ret
, "CloseHandle failed with last error %u\n", GetLastError());
1270 ret
= CloseHandle(pi
.hProcess
);
1271 ok(ret
, "CloseHandle failed with last error %u\n", GetLastError());
1274 static void test_query_process_debug_flags(int argc
, char **argv
)
1276 static const DWORD test_flags
[] = { DEBUG_PROCESS
,
1277 DEBUG_ONLY_THIS_PROCESS
,
1278 DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
,
1280 DWORD debug_flags
= 0xdeadbeef;
1281 char cmdline
[MAX_PATH
];
1282 PROCESS_INFORMATION pi
;
1283 STARTUPINFOA si
= { 0 };
1290 /* test invalid arguments */
1291 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
, NULL
, 0, NULL
);
1292 ok(status
== STATUS_INFO_LENGTH_MISMATCH
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1293 "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1295 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
, NULL
, sizeof(debug_flags
), NULL
);
1296 ok(status
== STATUS_INVALID_HANDLE
|| status
== STATUS_ACCESS_VIOLATION
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1297 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1299 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1300 NULL
, sizeof(debug_flags
), NULL
);
1301 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status
);
1303 status
= pNtQueryInformationProcess(NULL
, ProcessDebugFlags
,
1304 &debug_flags
, sizeof(debug_flags
), NULL
);
1305 ok(status
== STATUS_INVALID_HANDLE
|| broken(status
== STATUS_INVALID_INFO_CLASS
) /* WOW64 */,
1306 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status
);
1308 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1309 &debug_flags
, sizeof(debug_flags
) - 1, NULL
);
1310 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1312 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1313 &debug_flags
, sizeof(debug_flags
) + 1, NULL
);
1314 ok(status
== STATUS_INFO_LENGTH_MISMATCH
, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status
);
1316 /* test ProcessDebugFlags of current process */
1317 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags
,
1318 &debug_flags
, sizeof(debug_flags
), NULL
);
1319 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1320 ok(debug_flags
== TRUE
, "Expected flag TRUE, got %x.\n", debug_flags
);
1322 for (i
= 0; i
< sizeof(test_flags
)/sizeof(test_flags
[0]); i
++)
1324 DWORD expected_flags
= !(test_flags
[i
] & DEBUG_ONLY_THIS_PROCESS
);
1325 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], "debuggee");
1328 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, test_flags
[i
], NULL
, NULL
, &si
, &pi
);
1329 ok(ret
, "CreateProcess failed, last error %#x.\n", GetLastError());
1331 if (!(test_flags
[i
] & (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
)))
1333 /* test ProcessDebugFlags before attaching with debugger */
1334 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1335 &debug_flags
, sizeof(debug_flags
), NULL
);
1336 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1337 ok(debug_flags
== TRUE
, "Expected flag TRUE, got %x.\n", debug_flags
);
1339 ret
= DebugActiveProcess(pi
.dwProcessId
);
1340 ok(ret
, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1341 expected_flags
= FALSE
;
1344 /* test ProcessDebugFlags after attaching with debugger */
1345 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1346 &debug_flags
, sizeof(debug_flags
), NULL
);
1347 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1348 ok(debug_flags
== expected_flags
, "Expected flag %x, got %x.\n", expected_flags
, debug_flags
);
1350 if (!(test_flags
[i
] & CREATE_SUSPENDED
))
1352 /* Continue a couple of times to make sure the process is fully initialized,
1353 * otherwise Windows XP deadlocks in the following DebugActiveProcess(). */
1356 ret
= WaitForDebugEvent(&ev
, 1000);
1357 ok(ret
, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1360 if (ev
.dwDebugEventCode
== LOAD_DLL_DEBUG_EVENT
) break;
1362 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1363 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1367 result
= SuspendThread(pi
.hThread
);
1368 ok(result
== 0, "Expected 0, got %u.\n", result
);
1371 ret
= DebugActiveProcessStop(pi
.dwProcessId
);
1372 ok(ret
, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError());
1374 /* test ProcessDebugFlags after detaching debugger */
1375 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1376 &debug_flags
, sizeof(debug_flags
), NULL
);
1377 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1378 ok(debug_flags
== expected_flags
, "Expected flag %x, got %x.\n", expected_flags
, debug_flags
);
1380 ret
= DebugActiveProcess(pi
.dwProcessId
);
1381 ok(ret
, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1383 /* test ProcessDebugFlags after re-attaching debugger */
1384 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1385 &debug_flags
, sizeof(debug_flags
), NULL
);
1386 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1387 ok(debug_flags
== FALSE
, "Expected flag FALSE, got %x.\n", debug_flags
);
1389 result
= ResumeThread(pi
.hThread
);
1390 todo_wine
ok(result
== 2, "Expected 2, got %u.\n", result
);
1392 /* Wait until the process is terminated. On Windows XP the process randomly
1393 * gets stuck in a non-continuable exception, so stop after 100 iterations.
1394 * On Windows 2003, the debugged process disappears (or stops?) without
1395 * any EXIT_PROCESS_DEBUG_EVENT after a couple of events. */
1396 for (j
= 0; j
< 100; j
++)
1398 ret
= WaitForDebugEvent(&ev
, 1000);
1399 ok(ret
|| broken(GetLastError() == ERROR_SEM_TIMEOUT
),
1400 "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1403 if (ev
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
) break;
1405 ret
= ContinueDebugEvent(ev
.dwProcessId
, ev
.dwThreadId
, DBG_CONTINUE
);
1406 ok(ret
, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1409 ok(j
< 100 || broken(j
>= 100) /* Win XP */, "Expected less than 100 debug events.\n");
1411 /* test ProcessDebugFlags after process has terminated */
1412 status
= pNtQueryInformationProcess(pi
.hProcess
, ProcessDebugFlags
,
1413 &debug_flags
, sizeof(debug_flags
), NULL
);
1414 ok(!status
, "NtQueryInformationProcess failed, status %#x.\n", status
);
1415 ok(debug_flags
== FALSE
, "Expected flag FALSE, got %x.\n", debug_flags
);
1417 ret
= CloseHandle(pi
.hThread
);
1418 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1419 ret
= CloseHandle(pi
.hProcess
);
1420 ok(ret
, "CloseHandle failed, last error %#x.\n", GetLastError());
1424 static void test_readvirtualmemory(void)
1429 static const char teststring
[] = "test string";
1432 process
= OpenProcess(PROCESS_VM_READ
, FALSE
, GetCurrentProcessId());
1433 ok(process
!= 0, "Expected to be able to open own process for reading memory\n");
1435 /* normal operation */
1436 status
= pNtReadVirtualMemory(process
, teststring
, buffer
, 12, &readcount
);
1437 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1438 ok( readcount
== 12, "Expected to read 12 bytes, got %ld\n",readcount
);
1439 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1441 /* no number of bytes */
1442 memset(buffer
, 0, 12);
1443 status
= pNtReadVirtualMemory(process
, teststring
, buffer
, 12, NULL
);
1444 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1445 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1447 /* illegal remote address */
1449 status
= pNtReadVirtualMemory(process
, (void *) 0x1234, buffer
, 12, &readcount
);
1450 ok( status
== STATUS_PARTIAL_COPY
|| broken(status
== STATUS_ACCESS_VIOLATION
), "Expected STATUS_PARTIAL_COPY, got %08x\n", status
);
1451 if (status
== STATUS_PARTIAL_COPY
)
1452 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1456 status
= pNtReadVirtualMemory(0, teststring
, buffer
, 12, &readcount
);
1457 ok( status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1458 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1460 /* pseudo handle for current process*/
1461 memset(buffer
, 0, 12);
1462 status
= pNtReadVirtualMemory((HANDLE
)-1, teststring
, buffer
, 12, &readcount
);
1463 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1464 ok( readcount
== 12, "Expected to read 12 bytes, got %ld\n",readcount
);
1465 ok( strcmp(teststring
, buffer
) == 0, "Expected read memory to be the same as original memory\n");
1467 /* illegal local address */
1468 status
= pNtReadVirtualMemory(process
, teststring
, (void *)0x1234, 12, &readcount
);
1469 ok( status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
1470 ok( readcount
== 0, "Expected to read 0 bytes, got %ld\n",readcount
);
1472 CloseHandle(process
);
1475 static void test_mapprotection(void)
1479 MEMORY_BASIC_INFORMATION info
;
1480 ULONG oldflags
, flagsize
, flags
= MEM_EXECUTE_OPTION_ENABLE
;
1481 LARGE_INTEGER size
, offset
;
1483 SIZE_T retlen
, count
;
1487 skip("No NtClose ... Win98\n");
1490 /* Switch to being a noexec unaware process */
1491 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &oldflags
, sizeof (oldflags
), &flagsize
);
1492 if (status
== STATUS_INVALID_PARAMETER
) {
1493 skip("Invalid Parameter on ProcessExecuteFlags query?\n");
1496 ok( (status
== STATUS_SUCCESS
) || (status
== STATUS_INVALID_INFO_CLASS
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1497 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &flags
, sizeof(flags
) );
1498 ok( (status
== STATUS_SUCCESS
) || (status
== STATUS_INVALID_INFO_CLASS
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1500 size
.u
.LowPart
= 0x1000;
1501 size
.u
.HighPart
= 0;
1502 status
= pNtCreateSection ( &h
,
1503 STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
1507 SEC_COMMIT
| SEC_NOCACHE
,
1510 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1512 offset
.u
.LowPart
= 0;
1513 offset
.u
.HighPart
= 0;
1516 status
= pNtMapViewOfSection ( h
, GetCurrentProcess(), &addr
, 0, 0, &offset
, &count
, ViewShare
, 0, PAGE_READWRITE
);
1517 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1519 #if defined(__x86_64__) || defined(__i386__)
1520 *(unsigned char*)addr
= 0xc3; /* lret ... in both i386 and x86_64 */
1521 #elif defined(__arm__)
1522 *(unsigned long*)addr
= 0xe12fff1e; /* bx lr */
1523 #elif defined(__aarch64__)
1524 *(unsigned long*)addr
= 0xd65f03c0; /* ret */
1526 ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
1528 trace("trying to execute code in the readwrite only mapped anon file...\n");
1530 trace("...done.\n");
1532 status
= pNtQueryVirtualMemory( GetCurrentProcess(), addr
, MemoryBasicInformation
, &info
, sizeof(info
), &retlen
);
1533 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1534 ok( retlen
== sizeof(info
), "Expected STATUS_SUCCESS, got %08x\n", status
);
1535 ok((info
.Protect
& ~PAGE_NOCACHE
) == PAGE_READWRITE
, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info
.Protect
);
1537 status
= pNtUnmapViewOfSection (GetCurrentProcess(), addr
);
1538 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1542 pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags
, &oldflags
, sizeof(oldflags
) );
1545 static void test_queryvirtualmemory(void)
1549 static const char teststring
[] = "test string";
1550 static char datatestbuf
[42] = "abc";
1551 static char rwtestbuf
[42];
1552 MEMORY_BASIC_INFORMATION mbi
;
1556 module
= GetModuleHandleA( "ntdll.dll" );
1557 trace("Check flags of the PE header of NTDLL.DLL at %p\n", module
);
1558 status
= pNtQueryVirtualMemory(NtCurrentProcess(), module
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1559 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1560 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1561 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1562 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1563 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1564 ok (mbi
.Protect
== PAGE_READONLY
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_READONLY
);
1565 ok (mbi
.Type
== MEM_IMAGE
, "mbi.Type is 0x%x, expected 0x%x\n", mbi
.Type
, MEM_IMAGE
);
1567 trace("Check flags of a function entry in NTDLL.DLL at %p\n", pNtQueryVirtualMemory
);
1568 module
= GetModuleHandleA( "ntdll.dll" );
1569 status
= pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1570 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1571 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1572 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1573 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1574 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1575 ok (mbi
.Protect
== PAGE_EXECUTE_READ
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_EXECUTE_READ
);
1577 trace("Check flags of heap at %p\n", GetProcessHeap());
1578 status
= pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1579 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1580 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1581 ok (mbi
.AllocationProtect
== PAGE_READWRITE
|| mbi
.AllocationProtect
== PAGE_EXECUTE_READWRITE
,
1582 "mbi.AllocationProtect is 0x%x\n", mbi
.AllocationProtect
);
1583 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1584 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_EXECUTE_READWRITE
,
1585 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1587 trace("Check flags of stack at %p\n", stackbuf
);
1588 status
= pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1589 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1590 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1591 ok (mbi
.AllocationProtect
== PAGE_READWRITE
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_READWRITE
);
1592 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%x\n", mbi
.State
, MEM_COMMIT
);
1593 ok (mbi
.Protect
== PAGE_READWRITE
, "mbi.Protect is 0x%x, expected 0x%x\n", mbi
.Protect
, PAGE_READWRITE
);
1595 trace("Check flags of read-only data at %p\n", teststring
);
1596 module
= GetModuleHandleA( NULL
);
1597 status
= pNtQueryVirtualMemory(NtCurrentProcess(), teststring
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1598 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1599 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1600 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1601 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1602 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1603 if (mbi
.Protect
!= PAGE_READONLY
)
1604 todo_wine
ok( mbi
.Protect
== PAGE_READONLY
, "mbi.Protect is 0x%x, expected 0x%X\n", mbi
.Protect
, PAGE_READONLY
);
1606 trace("Check flags of read-write data at %p\n", datatestbuf
);
1607 status
= pNtQueryVirtualMemory(NtCurrentProcess(), datatestbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1608 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1609 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1610 ok (mbi
.AllocationBase
== module
, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi
.AllocationBase
, module
);
1611 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1612 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1613 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_WRITECOPY
,
1614 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1616 trace("Check flags of read-write uninitialized data (.bss) at %p\n", rwtestbuf
);
1617 status
= pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf
, MemoryBasicInformation
, &mbi
, sizeof(MEMORY_BASIC_INFORMATION
), &readcount
);
1618 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1619 ok( readcount
== sizeof(MEMORY_BASIC_INFORMATION
), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION
),readcount
);
1620 if (mbi
.AllocationBase
== module
)
1622 ok (mbi
.AllocationProtect
== PAGE_EXECUTE_WRITECOPY
, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi
.AllocationProtect
, PAGE_EXECUTE_WRITECOPY
);
1623 ok (mbi
.State
== MEM_COMMIT
, "mbi.State is 0x%x, expected 0x%X\n", mbi
.State
, MEM_COMMIT
);
1624 ok (mbi
.Protect
== PAGE_READWRITE
|| mbi
.Protect
== PAGE_WRITECOPY
,
1625 "mbi.Protect is 0x%x\n", mbi
.Protect
);
1627 else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
1630 static void test_affinity(void)
1633 PROCESS_BASIC_INFORMATION pbi
;
1634 DWORD_PTR proc_affinity
, thread_affinity
;
1635 THREAD_BASIC_INFORMATION tbi
;
1639 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1640 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1641 proc_affinity
= pbi
.AffinityMask
;
1642 ok( proc_affinity
== (1 << si
.dwNumberOfProcessors
) - 1, "Unexpected process affinity\n" );
1643 proc_affinity
= 1 << si
.dwNumberOfProcessors
;
1644 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1645 ok( status
== STATUS_INVALID_PARAMETER
,
1646 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1649 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1650 ok( status
== STATUS_INVALID_PARAMETER
,
1651 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1653 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1654 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1655 ok( tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1, "Unexpected thread affinity\n" );
1656 thread_affinity
= 1 << si
.dwNumberOfProcessors
;
1657 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1658 ok( status
== STATUS_INVALID_PARAMETER
,
1659 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1660 thread_affinity
= 0;
1661 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1662 ok( status
== STATUS_INVALID_PARAMETER
,
1663 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1665 thread_affinity
= 1;
1666 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1667 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1668 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1669 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1670 ok( tbi
.AffinityMask
== 1, "Unexpected thread affinity\n" );
1672 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
1673 thread_affinity
= ~(DWORD_PTR
)0;
1674 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1675 ok( broken(status
== STATUS_INVALID_PARAMETER
) || status
== STATUS_SUCCESS
,
1676 "Expected STATUS_SUCCESS, got %08x\n", status
);
1678 if (si
.dwNumberOfProcessors
<= 1)
1680 skip("only one processor, skipping affinity testing\n");
1684 /* Test thread affinity mask resulting from "all processors" flag */
1685 if (status
== STATUS_SUCCESS
)
1687 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1688 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1689 ok( broken(tbi
.AffinityMask
== 1) || tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1,
1690 "Unexpected thread affinity\n" );
1693 skip("Cannot test thread affinity mask for 'all processors' flag\n");
1696 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1697 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1698 status
= pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1699 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1700 proc_affinity
= pbi
.AffinityMask
;
1701 ok( proc_affinity
== 2, "Unexpected process affinity\n" );
1702 /* Setting the process affinity changes the thread affinity to match */
1703 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1704 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1705 ok( tbi
.AffinityMask
== 2, "Unexpected thread affinity\n" );
1706 /* The thread affinity is restricted to the process affinity */
1707 thread_affinity
= 1;
1708 status
= pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask
, &thread_affinity
, sizeof(thread_affinity
) );
1709 ok( status
== STATUS_INVALID_PARAMETER
,
1710 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status
);
1712 proc_affinity
= (1 << si
.dwNumberOfProcessors
) - 1;
1713 status
= pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask
, &proc_affinity
, sizeof(proc_affinity
) );
1714 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1715 /* Resetting the process affinity also resets the thread affinity */
1716 status
= pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1717 ok( status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %08x\n", status
);
1718 ok( tbi
.AffinityMask
== (1 << si
.dwNumberOfProcessors
) - 1,
1719 "Unexpected thread affinity\n" );
1722 static void test_NtGetCurrentProcessorNumber(void)
1726 PROCESS_BASIC_INFORMATION pbi
;
1727 THREAD_BASIC_INFORMATION tbi
;
1728 DWORD_PTR old_process_mask
;
1729 DWORD_PTR old_thread_mask
;
1734 if (!pNtGetCurrentProcessorNumber
) {
1735 win_skip("NtGetCurrentProcessorNumber not available\n");
1740 current_cpu
= pNtGetCurrentProcessorNumber();
1741 trace("dwNumberOfProcessors: %d, current processor: %d\n", si
.dwNumberOfProcessors
, current_cpu
);
1743 status
= pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation
, &pbi
, sizeof(pbi
), NULL
);
1744 old_process_mask
= pbi
.AffinityMask
;
1745 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1747 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1748 old_thread_mask
= tbi
.AffinityMask
;
1749 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1751 /* allow the test to run on all processors */
1752 new_mask
= (1 << si
.dwNumberOfProcessors
) - 1;
1753 status
= pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask
, &new_mask
, sizeof(new_mask
));
1754 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1756 for (i
= 0; i
< si
.dwNumberOfProcessors
; i
++)
1759 status
= pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask
, &new_mask
, sizeof(new_mask
));
1760 ok(status
== STATUS_SUCCESS
, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i
, status
);
1762 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation
, &tbi
, sizeof(tbi
), NULL
);
1763 ok(status
== STATUS_SUCCESS
, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i
, status
);
1765 current_cpu
= pNtGetCurrentProcessorNumber();
1766 ok((current_cpu
== i
), "%d (new_mask 0x%lx): running on processor %d (AffinityMask: 0x%lx)\n",
1767 i
, new_mask
, current_cpu
, tbi
.AffinityMask
);
1770 /* restore old values */
1771 status
= pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask
, &old_process_mask
, sizeof(old_process_mask
));
1772 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1774 status
= pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask
, &old_thread_mask
, sizeof(old_thread_mask
));
1775 ok(status
== STATUS_SUCCESS
, "got 0x%x (expected STATUS_SUCCESS)\n", status
);
1778 static DWORD WINAPI
start_address_thread(void *arg
)
1780 PRTL_THREAD_START_ROUTINE entry
;
1786 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
1787 &entry
, sizeof(entry
), &ret
);
1788 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1789 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
1790 ok(entry
== (void *)start_address_thread
, "expected %p, got %p\n", start_address_thread
, entry
);
1794 static void test_thread_start_address(void)
1796 PRTL_THREAD_START_ROUTINE entry
, expected_entry
;
1797 IMAGE_NT_HEADERS
*nt
;
1803 module
= GetModuleHandleA(0);
1804 ok(module
!= NULL
, "expected non-NULL address for module\n");
1805 nt
= RtlImageNtHeader(module
);
1806 ok(nt
!= NULL
, "expected non-NULL address for NT header\n");
1810 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
1811 &entry
, sizeof(entry
), &ret
);
1812 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1813 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
1814 expected_entry
= (void *)((char *)module
+ nt
->OptionalHeader
.AddressOfEntryPoint
);
1815 ok(entry
== expected_entry
, "expected %p, got %p\n", expected_entry
, entry
);
1817 entry
= (void *)0xdeadbeef;
1818 status
= pNtSetInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
1819 &entry
, sizeof(entry
));
1820 ok(status
== STATUS_SUCCESS
|| status
== STATUS_INVALID_PARAMETER
, /* >= Vista */
1821 "expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER, got %08x\n", status
);
1823 if (status
== STATUS_SUCCESS
)
1827 status
= pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress
,
1828 &entry
, sizeof(entry
), &ret
);
1829 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1830 ok(ret
== sizeof(entry
), "NtQueryInformationThread returned %u bytes\n", ret
);
1831 ok(entry
== (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", entry
);
1834 thread
= CreateThread(NULL
, 0, start_address_thread
, NULL
, 0, NULL
);
1835 ok(thread
!= INVALID_HANDLE_VALUE
, "CreateThread failed with %d\n", GetLastError());
1836 ret
= WaitForSingleObject(thread
, 1000);
1837 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", ret
);
1838 CloseHandle(thread
);
1846 if(!InitFunctionPtrs())
1849 argc
= winetest_get_mainargs(&argv
);
1850 if (argc
>= 3) return; /* Child */
1852 /* NtQuerySystemInformation */
1854 /* 0x0 SystemBasicInformation */
1855 trace("Starting test_query_basic()\n");
1858 /* 0x1 SystemCpuInformation */
1859 trace("Starting test_query_cpu()\n");
1862 /* 0x2 SystemPerformanceInformation */
1863 trace("Starting test_query_performance()\n");
1864 test_query_performance();
1866 /* 0x3 SystemTimeOfDayInformation */
1867 trace("Starting test_query_timeofday()\n");
1868 test_query_timeofday();
1870 /* 0x5 SystemProcessInformation */
1871 trace("Starting test_query_process()\n");
1872 test_query_process();
1874 /* 0x8 SystemProcessorPerformanceInformation */
1875 trace("Starting test_query_procperf()\n");
1876 test_query_procperf();
1878 /* 0xb SystemModuleInformation */
1879 trace("Starting test_query_module()\n");
1880 test_query_module();
1882 /* 0x10 SystemHandleInformation */
1883 trace("Starting test_query_handle()\n");
1884 test_query_handle();
1886 /* 0x15 SystemCacheInformation */
1887 trace("Starting test_query_cache()\n");
1890 /* 0x17 SystemInterruptInformation */
1891 trace("Starting test_query_interrupt()\n");
1892 test_query_interrupt();
1894 /* 0x23 SystemKernelDebuggerInformation */
1895 trace("Starting test_query_kerndebug()\n");
1896 test_query_kerndebug();
1898 /* 0x25 SystemRegistryQuotaInformation */
1899 trace("Starting test_query_regquota()\n");
1900 test_query_regquota();
1902 /* 0x49 SystemLogicalProcessorInformation */
1903 trace("Starting test_query_logicalproc()\n");
1904 test_query_logicalproc();
1906 /* NtPowerInformation */
1908 /* 0xb ProcessorInformation */
1909 trace("Starting test_query_processor_power_info()\n");
1910 test_query_processor_power_info();
1912 /* NtQueryInformationProcess */
1914 /* 0x0 ProcessBasicInformation */
1915 trace("Starting test_query_process_basic()\n");
1916 test_query_process_basic();
1918 /* 0x2 ProcessIoCounters */
1919 trace("Starting test_query_process_io()\n");
1920 test_query_process_io();
1922 /* 0x3 ProcessVmCounters */
1923 trace("Starting test_query_process_vm()\n");
1924 test_query_process_vm();
1926 /* 0x4 ProcessTimes */
1927 trace("Starting test_query_process_times()\n");
1928 test_query_process_times();
1930 /* 0x7 ProcessDebugPort */
1931 trace("Starting test_process_debug_port()\n");
1932 test_query_process_debug_port(argc
, argv
);
1934 /* 0x14 ProcessHandleCount */
1935 trace("Starting test_query_process_handlecount()\n");
1936 test_query_process_handlecount();
1938 /* 0x1A ProcessWow64Information */
1939 trace("Starting test_query_process_wow64()\n");
1940 test_query_process_wow64();
1942 /* 0x1B ProcessImageFileName */
1943 trace("Starting test_query_process_image_file_name()\n");
1944 test_query_process_image_file_name();
1946 /* 0x1E ProcessDebugObjectHandle */
1947 trace("Starting test_query_process_debug_object_handle()\n");
1948 test_query_process_debug_object_handle(argc
, argv
);
1950 /* 0x1F ProcessDebugFlags */
1951 trace("Starting test_process_debug_flags()\n");
1952 test_query_process_debug_flags(argc
, argv
);
1954 /* belongs to its own file */
1955 trace("Starting test_readvirtualmemory()\n");
1956 test_readvirtualmemory();
1958 trace("Starting test_queryvirtualmemory()\n");
1959 test_queryvirtualmemory();
1961 trace("Starting test_mapprotection()\n");
1962 test_mapprotection();
1964 trace("Starting test_affinity()\n");
1967 trace("Starting test_NtGetCurrentProcessorNumber()\n");
1968 test_NtGetCurrentProcessorNumber();
1970 trace("Starting test_thread_start_address()\n");
1971 test_thread_start_address();