include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / ntdll / tests / info.c
blob8e8abbfb4676193f07d0f4a7b3343a6ea81f4d2c
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 <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winnls.h"
30 #include "ddk/ntddk.h"
31 #include "psapi.h"
32 #include "wine/test.h"
34 static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
35 static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG);
36 static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
37 static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
38 static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
39 static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
40 static NTSTATUS (WINAPI * pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
41 static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
42 static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
43 static NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *);
44 static NTSTATUS (WINAPI * pNtCreateSection)(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
45 static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG_PTR,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG);
46 static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID);
47 static NTSTATUS (WINAPI * pNtClose)(HANDLE);
48 static ULONG (WINAPI * pNtGetCurrentProcessorNumber)(void);
49 static BOOL (WINAPI * pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*);
50 static DEP_SYSTEM_POLICY_TYPE (WINAPI * pGetSystemDEPPolicy)(void);
51 static NTSTATUS (WINAPI * pNtOpenThread)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID *);
52 static NTSTATUS (WINAPI * pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void *, ULONG, ULONG *);
53 static NTSTATUS (WINAPI * pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG );
54 static NTSTATUS (WINAPI * pNtSetInformationDebugObject)(HANDLE,DEBUGOBJECTINFOCLASS,PVOID,ULONG,ULONG*);
55 static NTSTATUS (WINAPI * pDbgUiConvertStateChangeStructure)(DBGUI_WAIT_STATE_CHANGE*,DEBUG_EVENT*);
56 static HANDLE (WINAPI * pDbgUiGetThreadDebugObject)(void);
57 static void (WINAPI * pDbgUiSetThreadDebugObject)(HANDLE);
58 static NTSTATUS (WINAPI * pNtSystemDebugControl)(SYSDBG_COMMAND,PVOID,ULONG,PVOID,ULONG,PULONG);
60 static BOOL is_wow64;
61 static BOOL old_wow64;
63 /* one_before_last_pid is used to be able to compare values of a still running process
64 with the output of the test_query_process_times and test_query_process_handlecount tests.
66 static DWORD one_before_last_pid = 0;
68 static inline DWORD_PTR get_affinity_mask(DWORD num_cpus)
70 if (num_cpus >= sizeof(DWORD_PTR) * 8) return ~(DWORD_PTR)0;
71 return ((DWORD_PTR)1 << num_cpus) - 1;
74 #define NTDLL_GET_PROC(func) do { \
75 p ## func = (void*)GetProcAddress(hntdll, #func); \
76 if(!p ## func) { \
77 trace("GetProcAddress(%s) failed\n", #func); \
78 } \
79 } while(0)
81 /* Firmware table providers */
82 #define ACPI 0x41435049
83 #define FIRM 0x4649524D
84 #define RSMB 0x52534D42
86 static void InitFunctionPtrs(void)
88 /* All needed functions are NT based, so using GetModuleHandle is a good check */
89 HMODULE hntdll = GetModuleHandleA("ntdll");
90 HMODULE hkernel32 = GetModuleHandleA("kernel32");
92 NTDLL_GET_PROC(NtQuerySystemInformation);
93 NTDLL_GET_PROC(NtQuerySystemInformationEx);
94 NTDLL_GET_PROC(NtSetSystemInformation);
95 NTDLL_GET_PROC(RtlGetNativeSystemInformation);
96 NTDLL_GET_PROC(NtPowerInformation);
97 NTDLL_GET_PROC(NtQueryInformationThread);
98 NTDLL_GET_PROC(NtSetInformationProcess);
99 NTDLL_GET_PROC(NtSetInformationThread);
100 NTDLL_GET_PROC(NtReadVirtualMemory);
101 NTDLL_GET_PROC(NtQueryVirtualMemory);
102 NTDLL_GET_PROC(NtClose);
103 NTDLL_GET_PROC(NtCreateSection);
104 NTDLL_GET_PROC(NtMapViewOfSection);
105 NTDLL_GET_PROC(NtUnmapViewOfSection);
106 NTDLL_GET_PROC(NtOpenThread);
107 NTDLL_GET_PROC(NtQueryObject);
108 NTDLL_GET_PROC(NtCreateDebugObject);
109 NTDLL_GET_PROC(NtSetInformationDebugObject);
110 NTDLL_GET_PROC(NtGetCurrentProcessorNumber);
111 NTDLL_GET_PROC(DbgUiConvertStateChangeStructure);
112 NTDLL_GET_PROC(DbgUiGetThreadDebugObject);
113 NTDLL_GET_PROC(DbgUiSetThreadDebugObject);
114 NTDLL_GET_PROC(NtSystemDebugControl);
116 if (!IsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
118 if (is_wow64)
120 TEB64 *teb64 = ULongToPtr( NtCurrentTeb()->GdiBatchCount );
122 if (teb64)
124 PEB64 *peb64 = ULongToPtr(teb64->Peb);
125 old_wow64 = !peb64->LdrData;
129 pGetSystemDEPPolicy = (void *)GetProcAddress(hkernel32, "GetSystemDEPPolicy");
130 pGetLogicalProcessorInformationEx = (void *) GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
133 static void test_query_basic(void)
135 NTSTATUS status;
136 ULONG i, ReturnLength;
137 SYSTEM_BASIC_INFORMATION sbi, sbi2, sbi3;
139 /* This test also covers some basic parameter testing that should be the same for
140 * every information class
143 /* Use a nonexistent info class */
144 status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
145 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
146 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08lx\n", status);
148 /* Use an existing class but with a zero-length buffer */
149 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
150 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
152 /* Use an existing class, correct length but no SystemInformation buffer */
153 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
154 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER /* vista */,
155 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08lx\n", status);
157 /* Use an existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
158 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
159 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
161 /* Check a too large buffer size */
162 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
163 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
165 /* Finally some correct calls */
166 memset(&sbi, 0xcc, sizeof(sbi));
167 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
168 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
169 ok( sizeof(sbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
171 /* Check if we have some return values */
172 if (winetest_debug > 1) trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
173 ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
175 memset(&sbi2, 0xcc, sizeof(sbi2));
176 status = pRtlGetNativeSystemInformation(SystemBasicInformation, &sbi2, sizeof(sbi2), &ReturnLength);
177 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx.\n", status);
178 ok( sizeof(sbi2) == ReturnLength, "Unexpected length %lu.\n", ReturnLength);
180 ok( sbi.unknown == sbi2.unknown, "Expected unknown %#lx, got %#lx.\n", sbi.unknown, sbi2.unknown);
181 ok( sbi.KeMaximumIncrement == sbi2.KeMaximumIncrement, "Expected KeMaximumIncrement %lu, got %lu.\n",
182 sbi.KeMaximumIncrement, sbi2.KeMaximumIncrement);
183 ok( sbi.PageSize == sbi2.PageSize, "Expected PageSize field %lu, %lu.\n", sbi.PageSize, sbi2.PageSize);
184 ok( sbi.MmNumberOfPhysicalPages == sbi2.MmNumberOfPhysicalPages,
185 "Expected MmNumberOfPhysicalPages %lu, got %lu.\n",
186 sbi.MmNumberOfPhysicalPages, sbi2.MmNumberOfPhysicalPages);
187 ok( sbi.MmLowestPhysicalPage == sbi2.MmLowestPhysicalPage, "Expected MmLowestPhysicalPage %lu, got %lu.\n",
188 sbi.MmLowestPhysicalPage, sbi2.MmLowestPhysicalPage);
189 ok( sbi.MmHighestPhysicalPage == sbi2.MmHighestPhysicalPage, "Expected MmHighestPhysicalPage %lu, got %lu.\n",
190 sbi.MmHighestPhysicalPage, sbi2.MmHighestPhysicalPage);
191 /* Higher 32 bits of AllocationGranularity is sometimes garbage on Windows. */
192 ok( (ULONG)sbi.AllocationGranularity == (ULONG)sbi2.AllocationGranularity,
193 "Expected AllocationGranularity %#Ix, got %#Ix.\n",
194 sbi.AllocationGranularity, sbi2.AllocationGranularity);
195 ok( sbi.LowestUserAddress == sbi2.LowestUserAddress, "Expected LowestUserAddress %p, got %p.\n",
196 sbi.LowestUserAddress, sbi2.LowestUserAddress);
197 ok( sbi.ActiveProcessorsAffinityMask == sbi2.ActiveProcessorsAffinityMask,
198 "Expected ActiveProcessorsAffinityMask %#Ix, got %#Ix.\n",
199 sbi.ActiveProcessorsAffinityMask, sbi2.ActiveProcessorsAffinityMask);
200 ok( sbi.NumberOfProcessors == sbi2.NumberOfProcessors, "Expected NumberOfProcessors %u, got %u.\n",
201 sbi.NumberOfProcessors, sbi2.NumberOfProcessors);
202 #ifdef _WIN64
203 ok( sbi.HighestUserAddress == sbi2.HighestUserAddress, "Expected HighestUserAddress %p, got %p.\n",
204 (void *)sbi.HighestUserAddress, (void *)sbi2.HighestUserAddress);
205 #else
206 ok( sbi.HighestUserAddress == (void *)0x7ffeffff, "wrong limit %p\n", sbi.HighestUserAddress);
207 todo_wine_if( old_wow64 )
208 ok( sbi2.HighestUserAddress == (is_wow64 ? (void *)0xfffeffff : (void *)0x7ffeffff),
209 "wrong limit %p\n", sbi.HighestUserAddress);
210 #endif
212 memset(&sbi3, 0xcc, sizeof(sbi3));
213 status = pNtQuerySystemInformation(SystemNativeBasicInformation, &sbi3, sizeof(sbi3), &ReturnLength);
214 #ifdef _WIN64
215 ok( status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS), "got %08lx\n", status);
216 if (!status)
218 ok( sizeof(sbi3) == ReturnLength, "Unexpected length %lu.\n", ReturnLength);
219 ok( !memcmp( &sbi2, &sbi3, offsetof(SYSTEM_BASIC_INFORMATION,NumberOfProcessors)+1 ),
220 "info is different\n" );
222 #else
223 ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_SUCCESS), /* some Win8 */
224 "got %08lx\n", status);
225 status = pRtlGetNativeSystemInformation( SystemNativeBasicInformation, &sbi3, sizeof(sbi3), &ReturnLength );
226 ok( !status || status == STATUS_INFO_LENGTH_MISMATCH ||
227 broken(status == STATUS_INVALID_INFO_CLASS) || broken(status == STATUS_NOT_IMPLEMENTED),
228 "failed %lx\n", status );
229 if (!status || status == STATUS_INFO_LENGTH_MISMATCH)
230 todo_wine_if( old_wow64 )
231 ok( !status == !is_wow64, "got wrong status %lx wow64 %u\n", status, is_wow64 );
232 if (!status)
234 ok( sizeof(sbi3) == ReturnLength, "Unexpected length %lu.\n", ReturnLength);
235 ok( !memcmp( &sbi2, &sbi3, offsetof(SYSTEM_BASIC_INFORMATION,NumberOfProcessors)+1 ),
236 "info is different\n" );
238 else if (status == STATUS_INFO_LENGTH_MISMATCH)
240 /* SystemNativeBasicInformation uses the 64-bit structure on Wow64 */
241 struct
243 DWORD unknown;
244 ULONG KeMaximumIncrement;
245 ULONG PageSize;
246 ULONG MmNumberOfPhysicalPages;
247 ULONG MmLowestPhysicalPage;
248 ULONG MmHighestPhysicalPage;
249 ULONG64 AllocationGranularity;
250 ULONG64 LowestUserAddress;
251 ULONG64 HighestUserAddress;
252 ULONG64 ActiveProcessorsAffinityMask;
253 BYTE NumberOfProcessors;
254 } sbi64;
256 ok( ReturnLength == sizeof(sbi64), "len %lx\n", ReturnLength );
257 memset( &sbi64, 0xcc, sizeof(sbi64) );
258 ReturnLength = 0;
259 status = pRtlGetNativeSystemInformation( SystemNativeBasicInformation, &sbi64, sizeof(sbi64), &ReturnLength );
260 ok( !status, "failed %lx\n", status );
261 ok( ReturnLength == sizeof(sbi64), "len %lx\n", ReturnLength );
263 ok( sbi.unknown == sbi64.unknown, "unknown %#lx / %#lx\n", sbi.unknown, sbi64.unknown);
264 ok( sbi.KeMaximumIncrement == sbi64.KeMaximumIncrement, "KeMaximumIncrement %lu / %lu\n",
265 sbi.KeMaximumIncrement, sbi64.KeMaximumIncrement);
266 ok( sbi.PageSize == sbi64.PageSize, "PageSize %lu / %lu\n", sbi.PageSize, sbi64.PageSize);
267 ok( sbi.MmNumberOfPhysicalPages == sbi64.MmNumberOfPhysicalPages,
268 "MmNumberOfPhysicalPages %lu / %lu\n",
269 sbi.MmNumberOfPhysicalPages, sbi64.MmNumberOfPhysicalPages);
270 ok( sbi.MmLowestPhysicalPage == sbi64.MmLowestPhysicalPage, "MmLowestPhysicalPage %lu / %lu\n",
271 sbi.MmLowestPhysicalPage, sbi64.MmLowestPhysicalPage);
272 ok( sbi.MmHighestPhysicalPage == sbi64.MmHighestPhysicalPage, "MmHighestPhysicalPage %lu / %lu\n",
273 sbi.MmHighestPhysicalPage, sbi64.MmHighestPhysicalPage);
274 ok( sbi.AllocationGranularity == (ULONG_PTR)sbi64.AllocationGranularity,
275 "AllocationGranularity %#Ix / %#Ix\n", sbi.AllocationGranularity,
276 (ULONG_PTR)sbi64.AllocationGranularity);
277 ok( (ULONG_PTR)sbi.LowestUserAddress == sbi64.LowestUserAddress, "LowestUserAddress %p / %s\n",
278 sbi.LowestUserAddress, wine_dbgstr_longlong(sbi64.LowestUserAddress));
279 ok( sbi.ActiveProcessorsAffinityMask == sbi64.ActiveProcessorsAffinityMask,
280 "ActiveProcessorsAffinityMask %#Ix / %s\n",
281 sbi.ActiveProcessorsAffinityMask, wine_dbgstr_longlong(sbi64.ActiveProcessorsAffinityMask));
282 ok( sbi.NumberOfProcessors == sbi64.NumberOfProcessors, "NumberOfProcessors %u / %u\n",
283 sbi.NumberOfProcessors, sbi64.NumberOfProcessors);
284 ok( sbi64.HighestUserAddress == 0x7ffffffeffff, "wrong limit %s\n",
285 wine_dbgstr_longlong(sbi64.HighestUserAddress));
287 #endif
289 memset(&sbi3, 0xcc, sizeof(sbi3));
290 status = pNtQuerySystemInformation(SystemEmulationBasicInformation, &sbi3, sizeof(sbi3), &ReturnLength);
291 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx.\n", status);
292 ok( sizeof(sbi3) == ReturnLength, "Unexpected length %lu.\n", ReturnLength);
293 ok( !memcmp( &sbi, &sbi3, offsetof(SYSTEM_BASIC_INFORMATION,NumberOfProcessors)+1 ),
294 "info is different\n" );
296 for (i = 0; i < 256; i++)
298 NTSTATUS expect = pNtQuerySystemInformation( i, NULL, 0, &ReturnLength );
299 status = pRtlGetNativeSystemInformation( i, NULL, 0, &ReturnLength );
300 switch (i)
302 case SystemNativeBasicInformation:
303 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_INFO_LENGTH_MISMATCH ||
304 broken(status == STATUS_NOT_IMPLEMENTED) /* vista */, "%lu: %lx / %lx\n", i, status, expect );
305 break;
306 case SystemBasicInformation:
307 case SystemCpuInformation:
308 case SystemEmulationBasicInformation:
309 case SystemEmulationProcessorInformation:
310 ok( status == expect, "%lu: %lx / %lx\n", i, status, expect );
311 break;
312 default:
313 if (is_wow64) /* only a few info classes are supported on Wow64 */
314 todo_wine_if (is_wow64 && status != STATUS_INVALID_INFO_CLASS)
315 ok( status == STATUS_INVALID_INFO_CLASS ||
316 broken(status == STATUS_NOT_IMPLEMENTED), /* vista */
317 "%lu: %lx\n", i, status );
318 else
319 ok( status == expect, "%lu: %lx / %lx\n", i, status, expect );
320 break;
325 static void test_query_cpu(void)
327 NTSTATUS status;
328 ULONG len, buffer[16];
329 SYSTEM_PROCESSOR_FEATURES_INFORMATION features;
330 SYSTEM_CPU_INFORMATION sci, sci2, sci3;
332 memset(&sci, 0xcc, sizeof(sci));
333 status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &len);
334 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
335 ok( sizeof(sci) == len, "Inconsistent length %ld\n", len);
337 memset(&sci2, 0xcc, sizeof(sci2));
338 status = pRtlGetNativeSystemInformation(SystemCpuInformation, &sci2, sizeof(sci2), &len);
339 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx.\n", status);
340 ok( sizeof(sci2) == len, "Unexpected length %lu.\n", len);
342 if (is_wow64)
344 ok( sci.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL, "ProcessorArchitecture wrong %x\n",
345 sci.ProcessorArchitecture );
346 ok( sci2.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
347 sci2.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64,
348 "ProcessorArchitecture wrong %x\n", sci2.ProcessorArchitecture );
350 else
351 ok( sci.ProcessorArchitecture == sci2.ProcessorArchitecture,
352 "ProcessorArchitecture differs %x / %x\n",
353 sci.ProcessorArchitecture, sci2.ProcessorArchitecture );
355 if (sci2.ProcessorArchitecture != PROCESSOR_ARCHITECTURE_ARM64)
357 /* Check if we have some return values */
358 if (winetest_debug > 1) trace("Processor FeatureSet : %08lx\n", sci.ProcessorFeatureBits);
359 ok( sci.ProcessorFeatureBits != 0, "Expected some features for this processor, got %08lx\n",
360 sci.ProcessorFeatureBits);
362 ok( sci.ProcessorLevel == sci2.ProcessorLevel, "ProcessorLevel differs %x / %x\n",
363 sci.ProcessorLevel, sci2.ProcessorLevel );
364 ok( sci.ProcessorRevision == sci2.ProcessorRevision, "ProcessorRevision differs %x / %x\n",
365 sci.ProcessorRevision, sci2.ProcessorRevision );
366 ok( sci.MaximumProcessors == sci2.MaximumProcessors, "MaximumProcessors differs %x / %x\n",
367 sci.MaximumProcessors, sci2.MaximumProcessors );
368 ok( sci.ProcessorFeatureBits == sci2.ProcessorFeatureBits, "ProcessorFeatureBits differs %lx / %lx\n",
369 sci.ProcessorFeatureBits, sci2.ProcessorFeatureBits );
371 memset(&sci3, 0xcc, sizeof(sci3));
372 status = pNtQuerySystemInformation(SystemEmulationProcessorInformation, &sci3, sizeof(sci3), &len);
373 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx.\n", status);
374 ok( sizeof(sci3) == len, "Unexpected length %lu.\n", len);
376 #ifdef _WIN64
377 if (sci2.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)
378 ok( sci3.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM, "ProcessorArchitecture wrong %x\n",
379 sci3.ProcessorArchitecture );
380 else
381 ok( sci3.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL, "ProcessorArchitecture wrong %x\n",
382 sci3.ProcessorArchitecture );
383 #else
384 ok( sci.ProcessorArchitecture == sci3.ProcessorArchitecture,
385 "ProcessorArchitecture differs %x / %x\n",
386 sci.ProcessorArchitecture, sci3.ProcessorArchitecture );
387 #endif
388 ok( sci.ProcessorLevel == sci3.ProcessorLevel, "ProcessorLevel differs %x / %x\n",
389 sci.ProcessorLevel, sci3.ProcessorLevel );
390 ok( sci.ProcessorRevision == sci3.ProcessorRevision, "ProcessorRevision differs %x / %x\n",
391 sci.ProcessorRevision, sci3.ProcessorRevision );
392 ok( sci.MaximumProcessors == sci3.MaximumProcessors, "MaximumProcessors differs %x / %x\n",
393 sci.MaximumProcessors, sci3.MaximumProcessors );
394 ok( sci.ProcessorFeatureBits == sci3.ProcessorFeatureBits, "ProcessorFeatureBits differs %lx / %lx\n",
395 sci.ProcessorFeatureBits, sci3.ProcessorFeatureBits );
397 len = 0xdeadbeef;
398 status = pNtQuerySystemInformation( SystemProcessorFeaturesInformation, &features, sizeof(features), &len );
399 if (status != STATUS_NOT_SUPPORTED && status != STATUS_INVALID_INFO_CLASS)
401 ok( !status, "SystemProcessorFeaturesInformation failed %lx\n", status );
402 ok( len == sizeof(features), "wrong len %lu\n", len );
403 ok( (ULONG)features.ProcessorFeatureBits == sci.ProcessorFeatureBits, "wrong bits %I64x / %lx\n",
404 features.ProcessorFeatureBits, sci.ProcessorFeatureBits );
406 else skip( "SystemProcessorFeaturesInformation is not supported\n" );
408 len = 0xdeadbeef;
409 status = pNtQuerySystemInformation( SystemProcessorBrandString, buffer, sizeof(buffer), &len );
410 if (status != STATUS_NOT_SUPPORTED)
412 ok( !status, "SystemProcessorBrandString failed %lx\n", status );
413 ok( len == 49, "wrong len %lu\n", len );
414 trace( "got %s len %u\n", debugstr_a( (char *)buffer ), lstrlenA( (char *)buffer ));
416 len = 0xdeadbeef;
417 status = pNtQuerySystemInformation( SystemProcessorBrandString, buffer, 49, &len );
418 ok( !status, "SystemProcessorBrandString failed %lx\n", status );
419 ok( len == 49, "wrong len %lu\n", len );
421 len = 0xdeadbeef;
422 status = pNtQuerySystemInformation( SystemProcessorBrandString, buffer, 48, &len );
423 ok( status == STATUS_INFO_LENGTH_MISMATCH, "SystemProcessorBrandString failed %lx\n", status );
424 ok( len == 49, "wrong len %lu\n", len );
426 len = 0xdeadbeef;
427 status = pNtQuerySystemInformation( SystemProcessorBrandString, (char *)buffer + 1, 49, &len );
428 ok( status == STATUS_DATATYPE_MISALIGNMENT, "SystemProcessorBrandString failed %lx\n", status );
429 ok( len == 0xdeadbeef, "wrong len %lu\n", len );
431 else skip( "SystemProcessorBrandString is not supported\n" );
434 static void test_query_performance(void)
436 NTSTATUS status;
437 ULONG ReturnLength;
438 ULONGLONG buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION)/sizeof(ULONGLONG) + 5];
439 DWORD size = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
441 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, 0, &ReturnLength);
442 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
444 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
445 if (status == STATUS_INFO_LENGTH_MISMATCH && is_wow64)
447 /* size is larger on wow64 under w2k8/win7 */
448 size += 16;
449 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
451 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
452 ok( ReturnLength == size, "Inconsistent length %ld\n", ReturnLength);
454 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size + 2, &ReturnLength);
455 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
456 ok( ReturnLength == size || ReturnLength == size + 2 /* win8+ */,
457 "Inconsistent length %ld\n", ReturnLength);
459 /* Not return values yet, as struct members are unknown */
462 static void test_query_timeofday(void)
464 NTSTATUS status;
465 ULONG ReturnLength;
467 /* Copy of our winternl.h structure turned into a private one */
468 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
469 LARGE_INTEGER liKeBootTime;
470 LARGE_INTEGER liKeSystemTime;
471 LARGE_INTEGER liExpTimeZoneBias;
472 ULONG uCurrentTimeZoneId;
473 DWORD dwUnknown1[5];
474 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
476 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
478 status = pNtQuerySystemInformation( SystemTimeOfDayInformation, &sti, 0, &ReturnLength );
479 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
480 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
482 sti.uCurrentTimeZoneId = 0xdeadbeef;
483 status = pNtQuerySystemInformation( SystemTimeOfDayInformation, &sti, 24, &ReturnLength );
484 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
485 ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%ld)\n", ReturnLength);
486 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
488 sti.uCurrentTimeZoneId = 0xdeadbeef;
489 status = pNtQuerySystemInformation( SystemTimeOfDayInformation, &sti, 32, &ReturnLength );
490 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
491 ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%ld)\n", ReturnLength);
492 ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
494 status = pNtQuerySystemInformation( SystemTimeOfDayInformation, &sti, 49, &ReturnLength );
495 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
496 ok( ReturnLength == 0 || ReturnLength == sizeof(sti) /* vista */,
497 "ReturnLength should be 0, it is (%ld)\n", ReturnLength);
499 status = pNtQuerySystemInformation( SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength );
500 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
501 ok( sizeof(sti) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
503 /* Check if we have some return values */
504 if (winetest_debug > 1) trace("uCurrentTimeZoneId : (%ld)\n", sti.uCurrentTimeZoneId);
507 static void test_query_process( BOOL extended )
509 NTSTATUS status;
510 DWORD last_pid;
511 ULONG ReturnLength;
512 int i = 0, k = 0;
513 PROCESS_BASIC_INFORMATION pbi;
514 THREAD_BASIC_INFORMATION tbi;
515 OBJECT_ATTRIBUTES attr;
516 CLIENT_ID cid;
517 HANDLE handle;
519 /* Copy of our winternl.h structure turned into a private one */
520 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
521 ULONG NextEntryOffset;
522 DWORD dwThreadCount;
523 LARGE_INTEGER WorkingSetPrivateSize;
524 ULONG HardFaultCount;
525 ULONG NumberOfThreadsHighWatermark;
526 ULONGLONG CycleTime;
527 FILETIME ftCreationTime;
528 FILETIME ftUserTime;
529 FILETIME ftKernelTime;
530 UNICODE_STRING ProcessName;
531 DWORD dwBasePriority;
532 HANDLE UniqueProcessId;
533 HANDLE ParentProcessId;
534 ULONG HandleCount;
535 ULONG SessionId;
536 ULONG_PTR UniqueProcessKey;
537 VM_COUNTERS_EX vmCounters;
538 IO_COUNTERS ioCounters;
539 SYSTEM_THREAD_INFORMATION ti[1];
540 } SYSTEM_PROCESS_INFORMATION_PRIVATE;
542 BOOL is_process_wow64 = FALSE, current_process_found = FALSE;
543 SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf;
544 SYSTEM_EXTENDED_THREAD_INFORMATION *ti;
545 SYSTEM_INFORMATION_CLASS info_class;
546 void *expected_address;
547 ULONG thread_info_size;
549 if (extended)
551 info_class = SystemExtendedProcessInformation;
552 thread_info_size = sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION);
554 else
556 info_class = SystemProcessInformation;
557 thread_info_size = sizeof(SYSTEM_THREAD_INFORMATION);
560 /* test ReturnLength */
561 ReturnLength = 0;
562 status = pNtQuerySystemInformation( info_class, NULL, 0, &ReturnLength);
563 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH got %08lx\n", status);
564 ok( ReturnLength > 0, "got 0 length\n" );
566 /* W2K3 and later returns the needed length, the rest returns 0. */
567 if (!ReturnLength)
569 win_skip( "Zero return length, skipping tests." );
570 return;
573 winetest_push_context( "extended %d", extended );
575 spi_buf = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
576 status = pNtQuerySystemInformation(info_class, spi_buf, ReturnLength, &ReturnLength);
578 /* Sometimes new process or threads appear between the call and increase the size,
579 * otherwise the previously returned buffer size should be sufficient. */
580 ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH,
581 "Expected STATUS_SUCCESS, got %08lx\n", status );
583 spi = spi_buf;
585 for (;;)
587 DWORD_PTR tid;
588 DWORD j;
590 winetest_push_context( "i %u (%s)", i, debugstr_w(spi->ProcessName.Buffer) );
592 i++;
594 last_pid = (DWORD_PTR)spi->UniqueProcessId;
595 ok( !(last_pid & 3), "Unexpected PID low bits: %p\n", spi->UniqueProcessId );
597 if (last_pid == GetCurrentProcessId())
598 current_process_found = TRUE;
600 if (extended && is_wow64 && spi->UniqueProcessId)
602 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
603 cid.UniqueProcess = spi->UniqueProcessId;
604 cid.UniqueThread = 0;
605 status = NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, &attr, &cid );
606 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
607 "Got unexpected status %#lx, pid %p.\n", status, spi->UniqueProcessId );
609 if (!status)
611 ULONG_PTR info;
613 status = NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL );
614 ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status );
615 is_process_wow64 = !!info;
616 NtClose( handle );
620 for (j = 0; j < spi->dwThreadCount; j++)
622 ti = (SYSTEM_EXTENDED_THREAD_INFORMATION *)((BYTE *)spi->ti + j * thread_info_size);
624 k++;
625 ok ( ti->ThreadInfo.ClientId.UniqueProcess == spi->UniqueProcessId,
626 "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
627 ti->ThreadInfo.ClientId.UniqueProcess, spi->UniqueProcessId );
629 tid = (DWORD_PTR)ti->ThreadInfo.ClientId.UniqueThread;
630 ok( !(tid & 3), "Unexpected TID low bits: %p\n", ti->ThreadInfo.ClientId.UniqueThread );
632 if (extended)
634 todo_wine ok( !!ti->StackBase, "Got NULL StackBase.\n" );
635 todo_wine ok( !!ti->StackLimit, "Got NULL StackLimit.\n" );
636 ok( !!ti->Win32StartAddress, "Got NULL Win32StartAddress.\n" );
638 cid.UniqueProcess = 0;
639 cid.UniqueThread = ti->ThreadInfo.ClientId.UniqueThread;
641 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
642 status = NtOpenThread( &handle, THREAD_QUERY_INFORMATION, &attr, &cid );
643 if (!status)
645 THREAD_BASIC_INFORMATION tbi;
647 status = pNtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
648 ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status );
649 expected_address = tbi.TebBaseAddress;
650 if (is_wow64 && is_process_wow64)
651 expected_address = (BYTE *)expected_address - 0x2000;
652 if (!is_wow64 && !is_process_wow64 && !tbi.TebBaseAddress)
653 win_skip( "Could not get TebBaseAddress, thread %lu.\n", j );
654 else
655 ok( ti->TebBase == expected_address || (is_wow64 && !expected_address && !!ti->TebBase),
656 "Got unexpected TebBase %p, expected %p.\n", ti->TebBase, expected_address );
658 NtClose( handle );
663 if (!spi->NextEntryOffset)
665 winetest_pop_context();
666 break;
668 one_before_last_pid = last_pid;
670 spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->NextEntryOffset);
671 winetest_pop_context();
673 ok( current_process_found, "Test process not found.\n" );
674 if (winetest_debug > 1) trace("%u processes, %u threads\n", i, k);
676 if (one_before_last_pid == 0) one_before_last_pid = last_pid;
678 HeapFree( GetProcessHeap(), 0, spi_buf);
680 for (i = 1; i < 4; ++i)
682 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
683 cid.UniqueProcess = ULongToHandle(GetCurrentProcessId() + i);
684 cid.UniqueThread = 0;
686 status = NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, &attr, &cid );
687 ok( status == STATUS_SUCCESS || broken( status == STATUS_ACCESS_DENIED ) /* wxppro */,
688 "NtOpenProcess returned:%lx\n", status );
689 if (status != STATUS_SUCCESS) continue;
691 status = NtQueryInformationProcess( handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
692 ok( status == STATUS_SUCCESS, "NtQueryInformationProcess returned:%lx\n", status );
693 ok( pbi.UniqueProcessId == GetCurrentProcessId(),
694 "Expected pid %p, got %p\n", ULongToHandle(GetCurrentProcessId()), ULongToHandle(pbi.UniqueProcessId) );
696 NtClose( handle );
699 for (i = 1; i < 4; ++i)
701 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
702 cid.UniqueProcess = 0;
703 cid.UniqueThread = ULongToHandle(GetCurrentThreadId() + i);
705 status = NtOpenThread( &handle, THREAD_QUERY_LIMITED_INFORMATION, &attr, &cid );
706 ok( status == STATUS_SUCCESS || broken( status == STATUS_ACCESS_DENIED ) /* wxppro */,
707 "NtOpenThread returned:%lx\n", status );
708 if (status != STATUS_SUCCESS) continue;
710 status = pNtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
711 ok( status == STATUS_SUCCESS, "NtQueryInformationThread returned:%lx\n", status );
712 ok( tbi.ClientId.UniqueThread == ULongToHandle(GetCurrentThreadId()),
713 "Expected tid %p, got %p\n", ULongToHandle(GetCurrentThreadId()), tbi.ClientId.UniqueThread );
715 NtClose( handle );
717 winetest_pop_context();
720 static void test_query_procperf(void)
722 NTSTATUS status;
723 ULONG ReturnLength;
724 ULONG NeededLength;
725 SYSTEM_BASIC_INFORMATION sbi;
726 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
728 /* Find out the number of processors */
729 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
730 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
731 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
733 sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
735 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
736 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
738 /* Try it for 1 processor */
739 sppi->KernelTime.QuadPart = 0xdeaddead;
740 sppi->UserTime.QuadPart = 0xdeaddead;
741 sppi->IdleTime.QuadPart = 0xdeaddead;
742 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
743 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
744 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
745 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
746 "Inconsistent length %ld\n", ReturnLength);
747 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
748 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
749 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
751 /* Try it for all processors */
752 sppi->KernelTime.QuadPart = 0xdeaddead;
753 sppi->UserTime.QuadPart = 0xdeaddead;
754 sppi->IdleTime.QuadPart = 0xdeaddead;
755 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
756 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
757 ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
758 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
759 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
760 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
762 /* A too large given buffer size */
763 sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
764 sppi->KernelTime.QuadPart = 0xdeaddead;
765 sppi->UserTime.QuadPart = 0xdeaddead;
766 sppi->IdleTime.QuadPart = 0xdeaddead;
767 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
768 ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH /* vista */,
769 "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
770 ok( NeededLength == ReturnLength, "Inconsistent length (%ld) <-> (%ld)\n", NeededLength, ReturnLength);
771 if (status == STATUS_SUCCESS)
773 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
774 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
775 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
777 else /* vista and 2008 */
779 ok (sppi->KernelTime.QuadPart == 0xdeaddead, "KernelTime changed\n");
780 ok (sppi->UserTime.QuadPart == 0xdeaddead, "UserTime changed\n");
781 ok (sppi->IdleTime.QuadPart == 0xdeaddead, "IdleTime changed\n");
784 HeapFree( GetProcessHeap(), 0, sppi);
787 static void test_query_module(void)
789 const RTL_PROCESS_MODULE_INFORMATION_EX *infoex;
790 RTL_PROCESS_MODULES *info;
791 NTSTATUS status;
792 ULONG size, i;
793 char *buffer;
795 status = pNtQuerySystemInformation(SystemModuleInformation, NULL, 0, &size);
796 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status);
797 ok(size > 0, "expected nonzero size\n");
799 info = malloc(size);
800 status = pNtQuerySystemInformation(SystemModuleInformation, info, size, &size);
801 ok(!status, "got %#lx\n", status);
803 ok(info->ModulesCount > 0, "Expected some modules to be loaded\n");
805 for (i = 0; i < info->ModulesCount; i++)
807 RTL_PROCESS_MODULE_INFORMATION *module = &info->Modules[i];
809 ok(module->LoadOrderIndex == i, "%lu: got index %u\n", i, module->LoadOrderIndex);
810 ok(module->ImageBaseAddress || is_wow64, "%lu: got NULL address for %s\n", i, module->Name);
811 ok(module->ImageSize, "%lu: got 0 size\n", i);
812 ok(module->LoadCount, "%lu: got 0 load count\n", i);
815 free(info);
817 status = pNtQuerySystemInformation(SystemModuleInformationEx, NULL, 0, &size);
818 if (status == STATUS_INVALID_INFO_CLASS)
820 win_skip("SystemModuleInformationEx is not supported.\n");
821 return;
823 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status);
824 ok(size > 0, "expected nonzero size\n");
826 buffer = malloc(size);
827 status = pNtQuerySystemInformation(SystemModuleInformationEx, buffer, size, &size);
828 ok(!status, "got %#lx\n", status);
830 infoex = (const void *)buffer;
831 for (i = 0; infoex->NextOffset; i++)
833 const RTL_PROCESS_MODULE_INFORMATION *module = &infoex->BaseInfo;
835 ok(module->LoadOrderIndex == i, "%lu: got index %u\n", i, module->LoadOrderIndex);
836 ok(module->ImageBaseAddress || is_wow64, "%lu: got NULL address for %s\n", i, module->Name);
837 ok(module->ImageSize, "%lu: got 0 size\n", i);
838 ok(module->LoadCount, "%lu: got 0 load count\n", i);
840 infoex = (const void *)((const char *)infoex + infoex->NextOffset);
842 ok(((char *)infoex - buffer) + sizeof(infoex->NextOffset) == size,
843 "got size %lu, null terminator %Iu\n", size, (char *)infoex - buffer);
845 free(buffer);
849 static void test_query_handle(void)
851 NTSTATUS status;
852 ULONG ExpectedLength, ReturnLength;
853 ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
854 SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
855 HANDLE EventHandle;
856 BOOL found, ret;
857 INT i;
859 EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL);
860 ok( EventHandle != NULL, "CreateEventA failed %lu\n", GetLastError() );
861 ret = SetHandleInformation(EventHandle, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
862 HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE);
863 ok(ret, "got error %lu\n", GetLastError());
865 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
866 ReturnLength = 0xdeadbeef;
867 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
868 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
869 ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
871 SystemInformationLength = ReturnLength;
872 shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
873 memset(shi, 0x55, SystemInformationLength);
875 ReturnLength = 0xdeadbeef;
876 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
877 while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
879 SystemInformationLength *= 2;
880 shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
881 memset(shi, 0x55, SystemInformationLength);
882 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
884 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
885 ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
886 ok( ReturnLength == ExpectedLength || broken(ReturnLength == ExpectedLength - sizeof(DWORD)), /* Vista / 2008 */
887 "Expected length %lu, got %lu\n", ExpectedLength, ReturnLength );
888 ok( shi->Count > 1, "Expected more than 1 handle, got %lu\n", shi->Count );
889 ok( shi->Handle[1].HandleValue != 0x5555 || broken( shi->Handle[1].HandleValue == 0x5555 ), /* Vista / 2008 */
890 "Uninitialized second handle\n" );
891 if (shi->Handle[1].HandleValue == 0x5555)
893 win_skip("Skipping broken SYSTEM_HANDLE_INFORMATION\n");
894 CloseHandle(EventHandle);
895 goto done;
898 found = FALSE;
899 for (i = 0; i < shi->Count; i++)
901 if (shi->Handle[i].OwnerPid == GetCurrentProcessId() &&
902 (HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle)
904 ok(shi->Handle[i].HandleFlags == (OBJ_INHERIT | OBJ_PROTECT_CLOSE),
905 "got attributes %#x\n", shi->Handle[i].HandleFlags);
906 found = TRUE;
907 break;
910 ok( found, "Expected to find event handle %p (pid %lx) in handle list\n", EventHandle, GetCurrentProcessId() );
912 ret = SetHandleInformation(EventHandle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
913 ok(ret, "got error %lu\n", GetLastError());
914 CloseHandle(EventHandle);
916 ReturnLength = 0xdeadbeef;
917 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
918 while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
920 SystemInformationLength *= 2;
921 shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
922 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
924 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
925 for (i = 0, found = FALSE; i < shi->Count && !found; i++)
926 found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
927 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
928 ok( !found, "Unexpectedly found event handle in handle list\n" );
930 status = pNtQuerySystemInformation(SystemHandleInformation, NULL, SystemInformationLength, &ReturnLength);
931 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status );
933 done:
934 HeapFree( GetProcessHeap(), 0, shi);
937 static void test_query_handle_ex(void)
939 SYSTEM_HANDLE_INFORMATION_EX *info = malloc(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
940 ULONG size, expect_size;
941 NTSTATUS status;
942 unsigned int i;
943 HANDLE event;
944 BOOL found, ret;
946 event = CreateEventA(NULL, FALSE, FALSE, NULL);
947 ok(event != NULL, "failed to create event, error %lu\n", GetLastError());
948 ret = SetHandleInformation(event, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
949 HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE);
950 ok(ret, "got error %lu\n", GetLastError());
952 size = 0;
953 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
954 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status);
955 ok(size > sizeof(SYSTEM_HANDLE_INFORMATION_EX), "got size %lu\n", size);
957 while (status == STATUS_INFO_LENGTH_MISMATCH)
959 info = realloc(info, size);
960 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
962 ok(!status, "got %#lx\n", status);
963 expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
964 ok(size == expect_size, "expected size %lu, got %lu\n", expect_size, size);
965 ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
967 found = FALSE;
968 for (i = 0; i < info->NumberOfHandles; ++i)
970 if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
971 && (HANDLE)info->Handles[i].HandleValue == event)
973 ok(info->Handles[i].HandleAttributes == (OBJ_INHERIT | OBJ_PROTECT_CLOSE),
974 "got flags %#lx\n", info->Handles[i].HandleAttributes);
975 ok(info->Handles[i].GrantedAccess == EVENT_ALL_ACCESS, "got access %#lx\n", info->Handles[i].GrantedAccess);
976 found = TRUE;
978 ok(!info->Handles[i].CreatorBackTraceIndex, "got backtrace index %u\n", info->Handles[i].CreatorBackTraceIndex);
980 ok(found, "event handle not found\n");
982 ret = SetHandleInformation(event, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
983 ok(ret, "got error %lu\n", GetLastError());
984 CloseHandle(event);
986 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
987 while (status == STATUS_INFO_LENGTH_MISMATCH)
989 info = realloc(info, size);
990 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
992 ok(!status, "got %#lx\n", status);
993 expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
994 ok(size == expect_size, "expected size %lu, got %lu\n", expect_size, size);
995 ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
997 found = FALSE;
998 for (i = 0; i < info->NumberOfHandles; ++i)
1000 if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
1001 && (HANDLE)info->Handles[i].HandleValue == event)
1003 found = TRUE;
1004 break;
1007 ok(!found, "event handle found\n");
1009 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
1010 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status );
1012 free(info);
1015 static void test_query_cache(void)
1017 NTSTATUS status;
1018 ULONG ReturnLength;
1019 BYTE buffer[128];
1020 SYSTEM_CACHE_INFORMATION *sci = (SYSTEM_CACHE_INFORMATION *) buffer;
1021 ULONG expected;
1022 INT i;
1024 expected = sizeof(SYSTEM_CACHE_INFORMATION);
1025 for (i = sizeof(buffer); i>= expected; i--)
1027 ReturnLength = 0xdeadbeef;
1028 status = pNtQuerySystemInformation(SystemFileCacheInformation, sci, i, &ReturnLength);
1029 ok(!status && (ReturnLength == expected),
1030 "%d: got 0x%lx and %lu (expected STATUS_SUCCESS and %lu)\n", i, status, ReturnLength, expected);
1033 /* buffer too small for the full result.
1034 Up to win7, the function succeeds with a partial result. */
1035 status = pNtQuerySystemInformation(SystemFileCacheInformation, sci, i, &ReturnLength);
1036 if (!status)
1038 expected = 3 * sizeof(ULONG);
1039 for (; i>= expected; i--)
1041 ReturnLength = 0xdeadbeef;
1042 status = pNtQuerySystemInformation(SystemFileCacheInformation, sci, i, &ReturnLength);
1043 ok(!status && (ReturnLength == expected),
1044 "%d: got 0x%lx and %lu (expected STATUS_SUCCESS and %lu)\n", i, status, ReturnLength, expected);
1048 /* buffer too small for the result, this call will always fail */
1049 ReturnLength = 0xdeadbeef;
1050 status = pNtQuerySystemInformation(SystemFileCacheInformation, sci, i, &ReturnLength);
1051 ok( status == STATUS_INFO_LENGTH_MISMATCH &&
1052 ((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
1053 "%d: got 0x%lx and %lu (expected STATUS_INFO_LENGTH_MISMATCH and %lu)\n", i, status, ReturnLength, expected);
1055 if (0) {
1056 /* this crashes on some vista / win7 machines */
1057 ReturnLength = 0xdeadbeef;
1058 status = pNtQuerySystemInformation(SystemFileCacheInformation, sci, 0, &ReturnLength);
1059 ok( status == STATUS_INFO_LENGTH_MISMATCH &&
1060 ((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
1061 "0: got 0x%lx and %lu (expected STATUS_INFO_LENGTH_MISMATCH and %lu)\n", status, ReturnLength, expected);
1065 static void test_query_interrupt(void)
1067 NTSTATUS status;
1068 ULONG ReturnLength;
1069 ULONG NeededLength;
1070 SYSTEM_BASIC_INFORMATION sbi;
1071 SYSTEM_INTERRUPT_INFORMATION* sii;
1073 /* Find out the number of processors */
1074 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
1075 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1076 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
1078 sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
1080 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
1081 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1082 ok(ReturnLength == NeededLength, "got %lu\n", ReturnLength);
1084 /* Try it for all processors */
1085 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
1086 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1088 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
1089 * No test added for this as it's highly unlikely that an app depends on this
1092 HeapFree( GetProcessHeap(), 0, sii);
1095 static void test_time_adjustment(void)
1097 SYSTEM_TIME_ADJUSTMENT_QUERY query;
1098 SYSTEM_TIME_ADJUSTMENT adjust;
1099 NTSTATUS status;
1100 ULONG len;
1102 memset( &query, 0xcc, sizeof(query) );
1103 status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query), &len );
1104 ok( status == STATUS_SUCCESS, "got %08lx\n", status );
1105 ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %lu\n", len );
1106 ok( query.TimeAdjustmentDisabled == TRUE || query.TimeAdjustmentDisabled == FALSE,
1107 "wrong value %x\n", query.TimeAdjustmentDisabled );
1109 status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query)-1, &len );
1110 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status );
1111 ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %lu\n", len );
1113 status = pNtQuerySystemInformation( SystemTimeAdjustmentInformation, &query, sizeof(query)+1, &len );
1114 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status );
1115 ok( len == sizeof(query) || broken(!len) /* winxp */, "wrong len %lu\n", len );
1117 adjust.TimeAdjustment = query.TimeAdjustment;
1118 adjust.TimeAdjustmentDisabled = query.TimeAdjustmentDisabled;
1119 status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust) );
1120 ok( status == STATUS_SUCCESS || status == STATUS_PRIVILEGE_NOT_HELD, "got %08lx\n", status );
1121 status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust)-1 );
1122 todo_wine
1123 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status );
1124 status = pNtSetSystemInformation( SystemTimeAdjustmentInformation, &adjust, sizeof(adjust)+1 );
1125 todo_wine
1126 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status );
1129 static void test_query_kerndebug(void)
1131 NTSTATUS status;
1132 ULONG ReturnLength;
1133 /* some Windows version expect alignment */
1134 SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX DECLSPEC_ALIGN(4) skdi_ex;
1135 SYSTEM_KERNEL_DEBUGGER_INFORMATION DECLSPEC_ALIGN(4) skdi;
1137 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
1138 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1140 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
1141 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1142 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1144 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
1145 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1146 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1148 status = pNtQuerySystemInformation(SystemKernelDebuggerInformationEx, &skdi_ex, 0, &ReturnLength);
1149 ok( status == STATUS_INFO_LENGTH_MISMATCH
1150 || status == STATUS_NOT_IMPLEMENTED /* before win7 */
1151 || status == STATUS_INVALID_INFO_CLASS /* wow64 on Win10 */,
1152 "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1154 if (status != STATUS_INFO_LENGTH_MISMATCH)
1156 win_skip( "NtQuerySystemInformation(SystemKernelDebuggerInformationEx) is not implemented.\n" );
1158 else
1160 status = pNtQuerySystemInformation(SystemKernelDebuggerInformationEx, &skdi_ex,
1161 sizeof(skdi_ex), &ReturnLength);
1162 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1163 ok( sizeof(skdi_ex) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1165 status = pNtQuerySystemInformation(SystemKernelDebuggerInformationEx, &skdi_ex,
1166 sizeof(skdi_ex) + 2, &ReturnLength);
1167 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1168 ok( sizeof(skdi_ex) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1172 static void test_query_regquota(void)
1174 NTSTATUS status;
1175 ULONG ReturnLength;
1176 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
1178 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
1179 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1181 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
1182 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1183 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1185 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
1186 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1187 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1190 static void test_query_logicalproc(void)
1192 NTSTATUS status;
1193 ULONG len, i, proc_no;
1194 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *slpi;
1195 SYSTEM_INFO si;
1197 GetSystemInfo(&si);
1199 status = pNtQuerySystemInformation(SystemLogicalProcessorInformation, NULL, 0, &len);
1200 if (status == STATUS_INVALID_INFO_CLASS) /* wow64 win8+, arm64 */
1202 skip("SystemLogicalProcessorInformation is not supported\n");
1203 return;
1205 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1206 ok(len%sizeof(*slpi) == 0, "Incorrect length %ld\n", len);
1208 slpi = HeapAlloc(GetProcessHeap(), 0, len);
1209 status = pNtQuerySystemInformation(SystemLogicalProcessorInformation, slpi, len, &len);
1210 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1212 proc_no = 0;
1213 for(i=0; i<len/sizeof(*slpi); i++) {
1214 switch(slpi[i].Relationship) {
1215 case RelationProcessorCore:
1216 /* Get number of logical processors */
1217 for(; slpi[i].ProcessorMask; slpi[i].ProcessorMask /= 2)
1218 proc_no += slpi[i].ProcessorMask%2;
1219 break;
1220 default:
1221 break;
1224 ok(proc_no > 0, "No processors were found\n");
1225 if(si.dwNumberOfProcessors <= 32)
1226 ok(proc_no == si.dwNumberOfProcessors, "Incorrect number of logical processors: %ld, expected %ld\n",
1227 proc_no, si.dwNumberOfProcessors);
1229 HeapFree(GetProcessHeap(), 0, slpi);
1232 static void test_query_logicalprocex(void)
1234 static const char * const names[] = { "Core", "NumaNode", "Cache", "Package", "Group", "Die", "NumaNodeEx", "Module" };
1235 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infoex, *infoex_public, *infoex_core, *infoex_numa, *infoex_cache,
1236 *infoex_package, *infoex_group, *infoex_die, *infoex_numa_ex,
1237 *infoex_module, *ex;
1238 DWORD relationship, len, len_public, len_core, len_numa, len_cache, len_package, len_group, len_die, len_numa_ex,
1239 len_module, len_union, ret_len;
1240 unsigned int i, j;
1241 NTSTATUS status;
1242 BOOL ret;
1244 if (!pNtQuerySystemInformationEx)
1245 return;
1247 len = 0;
1248 relationship = RelationAll;
1249 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len);
1250 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1251 ok(len > 0, "got %lu\n", len);
1253 len_core = 0;
1254 relationship = RelationProcessorCore;
1255 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_core);
1256 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1257 ok(len_core > 0, "got %lu\n", len_core);
1259 len_numa = 0;
1260 relationship = RelationNumaNode;
1261 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_numa);
1262 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1263 ok(len_numa > 0, "got %lu\n", len_numa);
1265 len_cache = 0;
1266 relationship = RelationCache;
1267 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_cache);
1268 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1269 ok(len_cache > 0, "got %lu\n", len_cache);
1271 len_package = 0;
1272 relationship = RelationProcessorPackage;
1273 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_package);
1274 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1275 ok(len_package > 0, "got %lu\n", len_package);
1277 len_group = 0;
1278 relationship = RelationGroup;
1279 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_group);
1280 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08lx\n", status);
1281 ok(len_group > 0, "got %lu\n", len_group);
1283 relationship = RelationProcessorDie;
1284 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_die);
1285 todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_UNSUCCESSFUL || broken(status == STATUS_SUCCESS),
1286 "got 0x%08lx\n", status);
1288 len_numa_ex = 0;
1289 relationship = RelationNumaNodeEx;
1290 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_numa_ex);
1291 todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_UNSUCCESSFUL || broken(status == STATUS_SUCCESS),
1292 "got 0x%08lx\n", status);
1294 len_module = 0;
1295 relationship = RelationProcessorModule;
1296 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len_module);
1297 todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_UNSUCCESSFUL || broken(status == STATUS_SUCCESS),
1298 "got 0x%08lx\n", status);
1300 len_public = 0;
1301 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, &len_public);
1302 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %ld\n", ret, GetLastError());
1303 ok(len == len_public, "got %lu, expected %lu\n", len_public, len);
1305 infoex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
1306 infoex_public = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_public);
1307 infoex_core = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_core);
1308 infoex_numa = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_numa);
1309 infoex_cache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_cache);
1310 infoex_package = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_package);
1311 infoex_group = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_group);
1312 infoex_die = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_die);
1313 infoex_numa_ex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_numa_ex);
1314 infoex_module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len_module);
1316 relationship = RelationAll;
1317 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex, len, &ret_len);
1318 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1319 ok(ret_len == len, "got %08lx expected %08lx\n", ret_len, len);
1321 ret = pGetLogicalProcessorInformationEx(RelationAll, infoex_public, &len_public);
1322 ok(ret, "got %d, error %ld\n", ret, GetLastError());
1323 ok(!memcmp(infoex, infoex_public, len), "returned info data mismatch\n");
1325 /* Test for RelationAll. */
1326 for (i = 0; status == STATUS_SUCCESS && i < len; )
1328 ex = (void *)(((char *)infoex) + i);
1329 ok(ex->Size, "%u: got size 0\n", i);
1331 if (winetest_debug <= 1)
1333 i += ex->Size;
1334 continue;
1337 trace("infoex[%u].Size: %lu\n", i, ex->Size);
1338 switch (ex->Relationship)
1340 case RelationProcessorCore:
1341 case RelationProcessorPackage:
1342 case RelationProcessorDie:
1343 case RelationProcessorModule:
1344 trace("infoex[%u].Relationship: 0x%x (%s)\n", i, ex->Relationship, names[ex->Relationship]);
1345 trace("infoex[%u].Processor.Flags: 0x%x\n", i, ex->Processor.Flags);
1346 trace("infoex[%u].Processor.EfficiencyClass: 0x%x\n", i, ex->Processor.EfficiencyClass);
1347 trace("infoex[%u].Processor.GroupCount: 0x%x\n", i, ex->Processor.GroupCount);
1348 for (j = 0; j < ex->Processor.GroupCount; ++j)
1350 trace("infoex[%u].Processor.GroupMask[%u].Mask: 0x%Ix\n", i, j, ex->Processor.GroupMask[j].Mask);
1351 trace("infoex[%u].Processor.GroupMask[%u].Group: 0x%x\n", i, j, ex->Processor.GroupMask[j].Group);
1353 break;
1354 case RelationNumaNode:
1355 case RelationNumaNodeEx:
1356 trace("infoex[%u].Relationship: 0x%x (%s)\n", i, ex->Relationship, names[ex->Relationship]);
1357 trace("infoex[%u].NumaNode.NodeNumber: 0x%lx\n", i, ex->NumaNode.NodeNumber);
1358 trace("infoex[%u].NumaNode.GroupMask.Mask: 0x%Ix\n", i, ex->NumaNode.GroupMask.Mask);
1359 trace("infoex[%u].NumaNode.GroupMask.Group: 0x%x\n", i, ex->NumaNode.GroupMask.Group);
1360 break;
1361 case RelationCache:
1362 trace("infoex[%u].Relationship: 0x%x (Cache)\n", i, ex->Relationship);
1363 trace("infoex[%u].Cache.Level: 0x%x\n", i, ex->Cache.Level);
1364 trace("infoex[%u].Cache.Associativity: 0x%x\n", i, ex->Cache.Associativity);
1365 trace("infoex[%u].Cache.LineSize: 0x%x\n", i, ex->Cache.LineSize);
1366 trace("infoex[%u].Cache.CacheSize: 0x%lx\n", i, ex->Cache.CacheSize);
1367 trace("infoex[%u].Cache.Type: 0x%x\n", i, ex->Cache.Type);
1368 trace("infoex[%u].Cache.GroupMask.Mask: 0x%Ix\n", i, ex->Cache.GroupMask.Mask);
1369 trace("infoex[%u].Cache.GroupMask.Group: 0x%x\n", i, ex->Cache.GroupMask.Group);
1370 break;
1371 case RelationGroup:
1372 trace("infoex[%u].Relationship: 0x%x (Group)\n", i, ex->Relationship);
1373 trace("infoex[%u].Group.MaximumGroupCount: 0x%x\n", i, ex->Group.MaximumGroupCount);
1374 trace("infoex[%u].Group.ActiveGroupCount: 0x%x\n", i, ex->Group.ActiveGroupCount);
1375 for (j = 0; j < ex->Group.ActiveGroupCount; ++j)
1377 trace("infoex[%u].Group.GroupInfo[%u].MaximumProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].MaximumProcessorCount);
1378 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorCount);
1379 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorMask: 0x%Ix\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorMask);
1381 break;
1382 default:
1383 ok(0, "Got invalid relationship value: 0x%x\n", ex->Relationship);
1384 break;
1387 i += ex->Size;
1390 /* Test Relationship filtering. */
1392 relationship = RelationProcessorCore;
1393 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex_core, len_core, &len_core);
1394 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1396 for (i = 0; status == STATUS_SUCCESS && i < len_core;)
1398 ex = (void *)(((char*)infoex_core) + i);
1399 ok(ex->Size, "%u: got size 0\n", i);
1400 ok(ex->Relationship == RelationProcessorCore, "%u: got relationship %#x\n", i, ex->Relationship);
1401 i += ex->Size;
1404 relationship = RelationNumaNode;
1405 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex_numa, len_numa, &len_numa);
1406 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1408 for (i = 0; status == STATUS_SUCCESS && i < len_numa;)
1410 ex = (void *)(((char*)infoex_numa) + i);
1411 ok(ex->Size, "%u: got size 0\n", i);
1412 ok(ex->Relationship == RelationNumaNode, "%u: got relationship %#x\n", i, ex->Relationship);
1413 i += ex->Size;
1416 relationship = RelationCache;
1417 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex_cache, len_cache, &len_cache);
1418 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1420 for (i = 0; status == STATUS_SUCCESS && i < len_cache;)
1422 ex = (void *)(((char*)infoex_cache) + i);
1423 ok(ex->Size, "%u: got size 0\n", i);
1424 ok(ex->Relationship == RelationCache, "%u: got relationship %#x\n", i, ex->Relationship);
1425 i += ex->Size;
1428 relationship = RelationProcessorPackage;
1429 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex_package, len_package, &len_package);
1430 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1432 for (i = 0; status == STATUS_SUCCESS && i < len_package;)
1434 ex = (void *)(((char*)infoex_package) + i);
1435 ok(ex->Size, "%u: got size 0\n", i);
1436 ok(ex->Relationship == RelationProcessorPackage, "%u: got relationship %#x\n", i, ex->Relationship);
1437 i += ex->Size;
1440 relationship = RelationGroup;
1441 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex_group, len_group, &len_group);
1442 ok(status == STATUS_SUCCESS, "got 0x%08lx\n", status);
1444 for (i = 0; status == STATUS_SUCCESS && i < len_group;)
1446 ex = (void *)(((char *)infoex_group) + i);
1447 ok(ex->Size, "%u: got size 0\n", i);
1448 ok(ex->Relationship == RelationGroup, "%u: got relationship %#x\n", i, ex->Relationship);
1449 i += ex->Size;
1452 len_union = len_core + len_numa + len_cache + len_package + len_group + len_module;
1453 ok(len == len_union, "Expected %lu, got %lu\n", len, len_union);
1455 HeapFree(GetProcessHeap(), 0, infoex);
1456 HeapFree(GetProcessHeap(), 0, infoex_public);
1457 HeapFree(GetProcessHeap(), 0, infoex_core);
1458 HeapFree(GetProcessHeap(), 0, infoex_numa);
1459 HeapFree(GetProcessHeap(), 0, infoex_cache);
1460 HeapFree(GetProcessHeap(), 0, infoex_package);
1461 HeapFree(GetProcessHeap(), 0, infoex_group);
1462 HeapFree(GetProcessHeap(), 0, infoex_die);
1463 HeapFree(GetProcessHeap(), 0, infoex_numa_ex);
1464 HeapFree(GetProcessHeap(), 0, infoex_module);
1467 static void test_query_cpusetinfo(void)
1469 SYSTEM_CPU_SET_INFORMATION *info;
1470 unsigned int i, cpu_count;
1471 ULONG len, expected_len;
1472 NTSTATUS status;
1473 SYSTEM_INFO si;
1474 HANDLE process;
1476 if (!pNtQuerySystemInformationEx)
1477 return;
1479 GetSystemInfo(&si);
1480 cpu_count = si.dwNumberOfProcessors;
1481 expected_len = cpu_count * sizeof(*info);
1483 process = GetCurrentProcess();
1485 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
1486 if (status == STATUS_INVALID_INFO_CLASS)
1488 win_skip("SystemCpuSetInformation is not supported\n");
1489 return;
1492 ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#lx.\n", status);
1493 ok(len == expected_len, "Got unexpected length %lu.\n", len);
1495 len = 0xdeadbeef;
1496 status = pNtQuerySystemInformation(SystemCpuSetInformation, NULL, 0, &len);
1497 ok(status == STATUS_INVALID_PARAMETER || status == STATUS_INVALID_INFO_CLASS,
1498 "Got unexpected status %#lx.\n", status);
1499 ok(len == 0xdeadbeef, "Got unexpected len %lu.\n", len);
1501 len = 0xdeadbeef;
1502 process = (HANDLE)0xdeadbeef;
1503 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
1504 ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#lx.\n", status);
1505 ok(len == 0xdeadbeef, "Got unexpected length %lu.\n", len);
1507 len = 0xdeadbeef;
1508 process = NULL;
1509 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, 4 * sizeof(process), NULL, 0, &len);
1510 ok((status == STATUS_INVALID_PARAMETER && len == 0xdeadbeef)
1511 || (status == STATUS_BUFFER_TOO_SMALL && len == expected_len),
1512 "Got unexpected status %#lx, length %lu.\n", status, len);
1514 len = 0xdeadbeef;
1515 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, NULL, sizeof(process), NULL, 0, &len);
1516 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
1517 ok(len == 0xdeadbeef, "Got unexpected length %lu.\n", len);
1519 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
1520 ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#lx.\n", status);
1521 ok(len == expected_len, "Got unexpected length %lu.\n", len);
1523 len = 0xdeadbeef;
1524 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL,
1525 expected_len, &len);
1526 ok(status == STATUS_ACCESS_VIOLATION, "Got unexpected status %#lx.\n", status);
1527 ok(len == 0xdeadbeef, "Got unexpected length %lu.\n", len);
1529 info = malloc(expected_len);
1530 len = 0;
1531 status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), info, expected_len, &len);
1532 ok(status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status);
1533 ok(len == expected_len, "Got unexpected length %lu.\n", len);
1535 for (i = 0; i < cpu_count; ++i)
1537 SYSTEM_CPU_SET_INFORMATION *d = &info[i];
1539 ok(d->Size == sizeof(*d), "Got unexpected size %lu, i %u.\n", d->Size, i);
1540 ok(d->Type == CpuSetInformation, "Got unexpected type %u, i %u.\n", d->Type, i);
1541 ok(d->CpuSet.Id == 0x100 + i, "Got unexpected Id %#lx, i %u.\n", d->CpuSet.Id, i);
1542 ok(!d->CpuSet.Group, "Got unexpected Group %u, i %u.\n", d->CpuSet.Group, i);
1543 ok(d->CpuSet.LogicalProcessorIndex == i, "Got unexpected LogicalProcessorIndex %u, i %u.\n",
1544 d->CpuSet.LogicalProcessorIndex, i);
1545 ok(!d->CpuSet.AllFlags, "Got unexpected AllFlags %#x, i %u.\n", d->CpuSet.AllFlags, i);
1547 free(info);
1550 static void test_query_firmware(void)
1552 static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
1553 ULONG len1, len2;
1554 NTSTATUS status;
1555 SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti;
1557 sfti = HeapAlloc(GetProcessHeap(), 0, sizeof(*sfti));
1558 ok(!!sfti, "Failed to allocate memory\n");
1560 sfti->ProviderSignature = 0;
1561 sfti->Action = 0;
1562 sfti->TableID = 0;
1564 status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len - 1, &len1);
1565 ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* xp */,
1566 "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1567 if (len1 == 0) /* xp, 2003 */
1569 win_skip("SystemFirmwareTableInformation is not available\n");
1570 HeapFree(GetProcessHeap(), 0, sfti);
1571 return;
1573 ok(len1 == min_sfti_len, "Expected length %lu, got %lu\n", min_sfti_len, len1);
1575 status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &len1);
1576 ok(status == STATUS_NOT_IMPLEMENTED, "Expected STATUS_NOT_IMPLEMENTED, got %08lx\n", status);
1577 ok(len1 == 0, "Expected length 0, got %lu\n", len1);
1579 sfti->ProviderSignature = RSMB;
1580 sfti->Action = SystemFirmwareTable_Get;
1582 status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &len1);
1583 ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08lx\n", status);
1584 ok(len1 >= min_sfti_len, "Expected length >= %lu, got %lu\n", min_sfti_len, len1);
1585 ok(sfti->TableBufferLength == len1 - min_sfti_len,
1586 "Expected length %lu, got %lu\n", len1 - min_sfti_len, sfti->TableBufferLength);
1588 sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, len1);
1589 ok(!!sfti, "Failed to allocate memory\n");
1591 status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, len1, &len2);
1592 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1593 ok(len2 == len1, "Expected length %lu, got %lu\n", len1, len2);
1594 ok(sfti->TableBufferLength == len1 - min_sfti_len,
1595 "Expected length %lu, got %lu\n", len1 - min_sfti_len, sfti->TableBufferLength);
1597 HeapFree(GetProcessHeap(), 0, sfti);
1600 static void test_query_battery(void)
1602 SYSTEM_BATTERY_STATE bs;
1603 NTSTATUS status;
1604 DWORD time_left;
1606 memset(&bs, 0x23, sizeof(bs));
1607 status = NtPowerInformation(SystemBatteryState, NULL, 0, &bs, sizeof(bs));
1608 if (status == STATUS_NOT_IMPLEMENTED)
1610 skip("SystemBatteryState not implemented\n");
1611 return;
1613 ok(status == STATUS_SUCCESS, "expected success\n");
1615 if (winetest_debug > 1)
1617 trace("Battery state:\n");
1618 trace("AcOnLine : %u\n", bs.AcOnLine);
1619 trace("BatteryPresent : %u\n", bs.BatteryPresent);
1620 trace("Charging : %u\n", bs.Charging);
1621 trace("Discharging : %u\n", bs.Discharging);
1622 trace("Tag : %u\n", bs.Tag);
1623 trace("MaxCapacity : %lu\n", bs.MaxCapacity);
1624 trace("RemainingCapacity : %lu\n", bs.RemainingCapacity);
1625 trace("Rate : %ld\n", (LONG)bs.Rate);
1626 trace("EstimatedTime : %lu\n", bs.EstimatedTime);
1627 trace("DefaultAlert1 : %lu\n", bs.DefaultAlert1);
1628 trace("DefaultAlert2 : %lu\n", bs.DefaultAlert2);
1631 ok(bs.MaxCapacity >= bs.RemainingCapacity,
1632 "expected MaxCapacity %lu to be greater than or equal to RemainingCapacity %lu\n",
1633 bs.MaxCapacity, bs.RemainingCapacity);
1635 if (!bs.BatteryPresent)
1636 time_left = 0;
1637 else if (!bs.Charging && (LONG)bs.Rate < 0)
1638 time_left = 3600 * bs.RemainingCapacity / -(LONG)bs.Rate;
1639 else
1640 time_left = ~0u;
1641 ok(bs.EstimatedTime == time_left,
1642 "expected %lu minutes remaining got %lu minutes\n", time_left, bs.EstimatedTime);
1645 static void test_query_processor_power_info(void)
1647 NTSTATUS status;
1648 PROCESSOR_POWER_INFORMATION* ppi;
1649 ULONG size;
1650 SYSTEM_INFO si;
1651 int i;
1653 GetSystemInfo(&si);
1654 size = si.dwNumberOfProcessors * sizeof(PROCESSOR_POWER_INFORMATION);
1655 ppi = HeapAlloc(GetProcessHeap(), 0, size);
1657 /* If size < (sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors), Win7 returns
1658 * STATUS_BUFFER_TOO_SMALL. WinXP returns STATUS_SUCCESS for any value of size. It copies as
1659 * many whole PROCESSOR_POWER_INFORMATION structures that there is room for. Even if there is
1660 * not enough room for one structure, WinXP still returns STATUS_SUCCESS having done nothing.
1662 * If ppi == NULL, Win7 returns STATUS_INVALID_PARAMETER while WinXP returns STATUS_SUCCESS
1663 * and does nothing.
1665 * The same behavior is seen with CallNtPowerInformation (in powrprof.dll).
1668 if (si.dwNumberOfProcessors > 1)
1670 for(i = 0; i < si.dwNumberOfProcessors; i++)
1671 ppi[i].Number = 0xDEADBEEF;
1673 /* Call with a buffer size that is large enough to hold at least one but not large
1674 * enough to hold them all. This will be STATUS_SUCCESS on WinXP but not on Win7 */
1675 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, size - sizeof(PROCESSOR_POWER_INFORMATION));
1676 if (status == STATUS_SUCCESS)
1678 /* lax version found on older Windows like WinXP */
1679 ok( (ppi[si.dwNumberOfProcessors - 2].Number != 0xDEADBEEF) &&
1680 (ppi[si.dwNumberOfProcessors - 1].Number == 0xDEADBEEF),
1681 "Expected all but the last record to be overwritten.\n");
1683 status = pNtPowerInformation(ProcessorInformation, 0, 0, 0, size);
1684 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1686 for(i = 0; i < si.dwNumberOfProcessors; i++)
1687 ppi[i].Number = 0xDEADBEEF;
1688 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, sizeof(PROCESSOR_POWER_INFORMATION) - 1);
1689 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1690 for(i = 0; i < si.dwNumberOfProcessors; i++)
1691 if (ppi[i].Number != 0xDEADBEEF) break;
1692 ok( i == si.dwNumberOfProcessors, "Expected untouched buffer\n");
1694 else
1696 /* picky version found on newer Windows like Win7 */
1697 ok( ppi[1].Number == 0xDEADBEEF, "Expected untouched buffer.\n");
1698 ok( status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08lx\n", status);
1700 status = pNtPowerInformation(ProcessorInformation, 0, 0, 0, size);
1701 ok( status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, "Got %08lx\n", status);
1703 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, 0);
1704 ok( status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INVALID_PARAMETER, "Got %08lx\n", status);
1707 else
1709 skip("Test needs more than one processor.\n");
1712 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, size);
1713 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1715 HeapFree(GetProcessHeap(), 0, ppi);
1718 static void test_query_process_wow64(void)
1720 NTSTATUS status;
1721 ULONG ReturnLength;
1722 ULONG_PTR pbi[2], dummy;
1724 memset(&dummy, 0xcc, sizeof(dummy));
1726 /* Do not give a handle and buffer */
1727 status = NtQueryInformationProcess(NULL, ProcessWow64Information, NULL, 0, NULL);
1728 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1730 /* Use a correct info class and buffer size, but still no handle and buffer */
1731 status = NtQueryInformationProcess(NULL, ProcessWow64Information, NULL, sizeof(ULONG_PTR), NULL);
1732 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1733 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE, got %08lx\n", status);
1735 /* Use a correct info class, buffer size and handle, but no buffer */
1736 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, NULL, sizeof(ULONG_PTR), NULL);
1737 ok( status == STATUS_ACCESS_VIOLATION , "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
1739 /* Use a correct info class, buffer and buffer size, but no handle */
1740 pbi[0] = pbi[1] = dummy;
1741 status = NtQueryInformationProcess(NULL, ProcessWow64Information, pbi, sizeof(ULONG_PTR), NULL);
1742 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1743 ok( pbi[0] == dummy, "pbi[0] changed to %Ix\n", pbi[0]);
1744 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1746 /* Use a greater buffer size */
1747 pbi[0] = pbi[1] = dummy;
1748 status = NtQueryInformationProcess(NULL, ProcessWow64Information, pbi, sizeof(ULONG_PTR) + 1, NULL);
1749 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1750 ok( pbi[0] == dummy, "pbi[0] changed to %Ix\n", pbi[0]);
1751 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1753 /* Use no ReturnLength */
1754 pbi[0] = pbi[1] = dummy;
1755 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR), NULL);
1756 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1757 ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %Ix\n", is_wow64, pbi[0]);
1758 if (is_wow64)
1759 ok( (void *)pbi[0] == NtCurrentTeb()->Peb, "pbi[0] %Ix / %p\n", pbi[0], NtCurrentTeb()->Peb);
1760 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1761 /* Test written size on 64 bit by checking high 32 bit buffer */
1762 if (sizeof(ULONG_PTR) > sizeof(DWORD))
1764 DWORD *ptr = (DWORD *)pbi;
1765 ok( ptr[1] != (DWORD)dummy, "ptr[1] unchanged!\n");
1768 /* Finally some correct calls */
1769 pbi[0] = pbi[1] = dummy;
1770 ReturnLength = 0xdeadbeef;
1771 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR), &ReturnLength);
1772 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1773 ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %Ix\n", is_wow64, pbi[0]);
1774 if (is_wow64)
1775 ok( (void *)pbi[0] == NtCurrentTeb()->Peb, "pbi[0] %Ix / %p\n", pbi[0], NtCurrentTeb()->Peb);
1776 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1777 ok( ReturnLength == sizeof(ULONG_PTR), "Inconsistent length %ld\n", ReturnLength);
1779 /* Everything is correct except a too small buffer size */
1780 pbi[0] = pbi[1] = dummy;
1781 ReturnLength = 0xdeadbeef;
1782 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR) - 1, &ReturnLength);
1783 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1784 ok( pbi[0] == dummy, "pbi[0] changed to %Ix\n", pbi[0]);
1785 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1786 ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", ReturnLength);
1788 /* Everything is correct except a too large buffer size */
1789 pbi[0] = pbi[1] = dummy;
1790 ReturnLength = 0xdeadbeef;
1791 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR) + 1, &ReturnLength);
1792 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1793 ok( pbi[0] == dummy, "pbi[0] changed to %Ix\n", pbi[0]);
1794 ok( pbi[1] == dummy, "pbi[1] changed to %Ix\n", pbi[1]);
1795 ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", ReturnLength);
1798 static void test_query_process_basic(void)
1800 NTSTATUS status;
1801 ULONG ReturnLength;
1803 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
1804 DWORD_PTR ExitStatus;
1805 PPEB PebBaseAddress;
1806 DWORD_PTR AffinityMask;
1807 DWORD_PTR BasePriority;
1808 ULONG_PTR UniqueProcessId;
1809 ULONG_PTR InheritedFromUniqueProcessId;
1810 } PROCESS_BASIC_INFORMATION_PRIVATE;
1812 PROCESS_BASIC_INFORMATION_PRIVATE pbi;
1814 /* This test also covers some basic parameter testing that should be the same for
1815 * every information class
1818 status = NtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
1819 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
1820 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08lx\n", status);
1822 status = NtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
1823 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1825 status = NtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
1826 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1827 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
1829 status = NtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
1830 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1832 status = NtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
1833 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1835 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
1836 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1838 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
1839 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1840 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1842 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
1843 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1844 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1846 if (winetest_debug > 1) trace("ProcessID : %Ix\n", pbi.UniqueProcessId);
1847 ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
1850 static void dump_vm_counters(const char *header, const VM_COUNTERS_EX *pvi)
1852 trace("%s:\n", header);
1853 trace("PeakVirtualSize : %Iu\n", pvi->PeakVirtualSize);
1854 trace("VirtualSize : %Iu\n", pvi->VirtualSize);
1855 trace("PageFaultCount : %lu\n", pvi->PageFaultCount);
1856 trace("PeakWorkingSetSize : %Iu\n", pvi->PeakWorkingSetSize);
1857 trace("WorkingSetSize : %Iu\n", pvi->WorkingSetSize);
1858 trace("QuotaPeakPagedPoolUsage : %Iu\n", pvi->QuotaPeakPagedPoolUsage);
1859 trace("QuotaPagedPoolUsage : %Iu\n", pvi->QuotaPagedPoolUsage);
1860 trace("QuotaPeakNonPagePoolUsage : %Iu\n", pvi->QuotaPeakNonPagedPoolUsage);
1861 trace("QuotaNonPagePoolUsage : %Iu\n", pvi->QuotaNonPagedPoolUsage);
1862 trace("PagefileUsage : %Iu\n", pvi->PagefileUsage);
1863 trace("PeakPagefileUsage : %Iu\n", pvi->PeakPagefileUsage);
1866 static void test_query_process_vm(void)
1868 NTSTATUS status;
1869 ULONG ReturnLength;
1870 VM_COUNTERS_EX pvi;
1871 HANDLE process;
1872 SIZE_T prev_size;
1873 const SIZE_T alloc_size = 16 * 1024 * 1024;
1874 void *ptr;
1876 status = NtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
1877 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1878 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
1880 status = NtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, sizeof(VM_COUNTERS), NULL);
1881 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1883 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
1884 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1886 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(VM_COUNTERS), &ReturnLength);
1887 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1888 ok( ReturnLength == sizeof(VM_COUNTERS), "Inconsistent length %ld\n", ReturnLength);
1890 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
1891 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1892 todo_wine ok( ReturnLength == sizeof(VM_COUNTERS), "wrong size %ld\n", ReturnLength);
1894 /* Check if we have some return values */
1895 if (winetest_debug > 1)
1896 dump_vm_counters("VM counters for GetCurrentProcess", &pvi);
1897 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
1898 ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
1900 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
1901 status = NtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1902 ok( status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got %08lx\n", status);
1903 CloseHandle(process);
1905 process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
1906 status = NtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1907 ok( status == STATUS_SUCCESS || broken(!process) /* XP */, "Expected STATUS_SUCCESS, got %08lx\n", status);
1908 CloseHandle(process);
1910 memset(&pvi, 0, sizeof(pvi));
1911 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
1912 status = NtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1913 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1914 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1916 /* Check if we have some return values */
1917 if (winetest_debug > 1)
1918 dump_vm_counters("VM counters for GetCurrentProcessId", &pvi);
1919 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
1920 ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
1922 CloseHandle(process);
1924 /* Check if we have real counters */
1925 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1926 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1927 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1928 prev_size = pvi.VirtualSize;
1929 if (winetest_debug > 1)
1930 dump_vm_counters("VM counters before VirtualAlloc", &pvi);
1931 ptr = VirtualAlloc(NULL, alloc_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
1932 ok( ptr != NULL, "VirtualAlloc failed, err %lu\n", GetLastError());
1933 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1934 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1935 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1936 if (winetest_debug > 1)
1937 dump_vm_counters("VM counters after VirtualAlloc", &pvi);
1938 todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
1939 "Expected to be greater than %Iu, got %Iu\n", prev_size + alloc_size, pvi.VirtualSize);
1940 VirtualFree( ptr, 0, MEM_RELEASE);
1942 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1943 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1944 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1945 prev_size = pvi.VirtualSize;
1946 if (winetest_debug > 1)
1947 dump_vm_counters("VM counters before VirtualAlloc", &pvi);
1948 ptr = VirtualAlloc(NULL, alloc_size, MEM_RESERVE, PAGE_READWRITE);
1949 ok( ptr != NULL, "VirtualAlloc failed, err %lu\n", GetLastError());
1950 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1951 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1952 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1953 if (winetest_debug > 1)
1954 dump_vm_counters("VM counters after VirtualAlloc(MEM_RESERVE)", &pvi);
1955 todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
1956 "Expected to be greater than %Iu, got %Iu\n", prev_size + alloc_size, pvi.VirtualSize);
1957 prev_size = pvi.VirtualSize;
1959 ptr = VirtualAlloc(ptr, alloc_size, MEM_COMMIT, PAGE_READWRITE);
1960 ok( ptr != NULL, "VirtualAlloc failed, err %lu\n", GetLastError());
1961 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1962 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1963 ok( pvi.PrivateUsage == pvi.PagefileUsage, "wrong value %Iu/%Iu\n", pvi.PrivateUsage, pvi.PagefileUsage );
1964 if (winetest_debug > 1)
1965 dump_vm_counters("VM counters after VirtualAlloc(MEM_COMMIT)", &pvi);
1966 ok( pvi.VirtualSize == prev_size,
1967 "Expected to equal to %Iu, got %Iu\n", prev_size, pvi.VirtualSize);
1968 VirtualFree( ptr, 0, MEM_RELEASE);
1971 static void test_query_process_io(void)
1973 NTSTATUS status;
1974 ULONG ReturnLength;
1975 IO_COUNTERS pii;
1977 status = NtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
1978 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1979 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
1981 status = NtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
1982 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1984 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
1985 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1987 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
1988 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
1989 ok( sizeof(pii) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1991 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
1992 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
1993 ok( sizeof(pii) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
1995 /* Check if we have some return values */
1996 if (winetest_debug > 1) trace("OtherOperationCount : 0x%s\n", wine_dbgstr_longlong(pii.OtherOperationCount));
1997 todo_wine
1999 ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
2003 static void test_query_process_times(void)
2005 NTSTATUS status;
2006 ULONG ReturnLength;
2007 HANDLE process;
2008 SYSTEMTIME UTC, Local;
2009 KERNEL_USER_TIMES spti;
2011 status = NtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
2012 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
2013 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
2015 status = NtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
2016 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2018 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
2019 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2021 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
2022 if (!process)
2024 if (winetest_debug > 1) trace("Could not open process with ID : %ld, error : %lu. Going to use current one.\n", one_before_last_pid, GetLastError());
2025 process = GetCurrentProcess();
2027 else
2028 trace("ProcessTimes for process with ID : %ld\n", one_before_last_pid);
2030 status = NtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
2031 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2032 ok( sizeof(spti) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
2033 CloseHandle(process);
2035 FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
2036 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
2037 if (winetest_debug > 1) trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
2038 Local.wHour, Local.wMinute, Local.wSecond);
2040 FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
2041 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
2042 if (winetest_debug > 1) trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
2043 Local.wHour, Local.wMinute, Local.wSecond);
2045 FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
2046 if (winetest_debug > 1) trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
2048 FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
2049 if (winetest_debug > 1) trace("UserTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
2051 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
2052 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2053 ok( sizeof(spti) == ReturnLength ||
2054 ReturnLength == 0 /* vista */ ||
2055 broken(is_wow64), /* returns garbage on wow64 */
2056 "Inconsistent length %ld\n", ReturnLength);
2059 static void test_query_process_debug_port(int argc, char **argv)
2061 DWORD_PTR debug_port = 0xdeadbeef;
2062 char cmdline[MAX_PATH];
2063 PROCESS_INFORMATION pi;
2064 STARTUPINFOA si = { 0 };
2065 NTSTATUS status;
2066 BOOL ret;
2067 ULONG len;
2069 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
2071 si.cb = sizeof(si);
2072 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
2073 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2074 if (!ret) return;
2076 status = NtQueryInformationProcess(NULL, ProcessDebugPort,
2077 NULL, 0, NULL);
2078 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2080 status = NtQueryInformationProcess(NULL, ProcessDebugPort,
2081 NULL, sizeof(debug_port), NULL);
2082 ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION /* XP */, "got %#lx\n", status);
2084 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
2085 NULL, sizeof(debug_port), NULL);
2086 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status);
2088 len = 0xdeadbeef;
2089 status = NtQueryInformationProcess(NULL, ProcessDebugPort,
2090 &debug_port, sizeof(debug_port), &len);
2091 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
2092 ok(len == 0xdeadbeef || broken(len != sizeof(debug_port)), /* wow64 */
2093 "len set to %lx\n", len );
2095 len = 0xdeadbeef;
2096 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
2097 &debug_port, sizeof(debug_port) - 1, &len);
2098 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2099 ok(len == 0xdeadbeef || broken(len != sizeof(debug_port)), /* wow64 */
2100 "len set to %lx\n", len );
2102 len = 0xdeadbeef;
2103 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
2104 &debug_port, sizeof(debug_port) + 1, &len);
2105 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2106 ok(len == 0xdeadbeef || broken(len != sizeof(debug_port)), /* wow64 */
2107 "len set to %lx\n", len );
2109 len = 0xdeadbeef;
2110 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
2111 &debug_port, sizeof(debug_port), &len);
2112 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2113 ok(debug_port == 0, "Expected port 0, got %#Ix.\n", debug_port);
2114 ok(len == sizeof(debug_port), "len set to %lx\n", len );
2116 len = 0xdeadbeef;
2117 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugPort,
2118 &debug_port, sizeof(debug_port), &len);
2119 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2120 ok(debug_port == ~(DWORD_PTR)0, "Expected port %#Ix, got %#Ix.\n", ~(DWORD_PTR)0, debug_port);
2121 ok(len == sizeof(debug_port), "len set to %lx\n", len );
2123 for (;;)
2125 DEBUG_EVENT ev;
2127 ret = WaitForDebugEvent(&ev, INFINITE);
2128 ok(ret, "WaitForDebugEvent failed, last error %#lx.\n", GetLastError());
2129 if (!ret) break;
2131 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
2133 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
2134 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
2135 if (!ret) break;
2138 ret = CloseHandle(pi.hThread);
2139 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2140 ret = CloseHandle(pi.hProcess);
2141 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2144 static void subtest_query_process_debug_port_custom_dacl(int argc, char **argv, ACCESS_MASK access, PSID sid)
2146 HANDLE old_debug_obj, debug_obj;
2147 OBJECT_ATTRIBUTES attr;
2148 SECURITY_DESCRIPTOR sd;
2149 union {
2150 ACL acl;
2151 DWORD buffer[(sizeof(ACL) +
2152 (offsetof(ACCESS_ALLOWED_ACE, SidStart) + SECURITY_MAX_SID_SIZE) +
2153 sizeof(DWORD) - 1) / sizeof(DWORD)];
2154 } acl;
2155 char cmdline[MAX_PATH];
2156 PROCESS_INFORMATION pi;
2157 STARTUPINFOA si;
2158 DEBUG_EVENT ev;
2159 NTSTATUS status;
2160 BOOL ret;
2162 InitializeAcl(&acl.acl, sizeof(acl), ACL_REVISION);
2163 AddAccessAllowedAce(&acl.acl, ACL_REVISION, access, sid);
2164 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
2165 SetSecurityDescriptorDacl(&sd, TRUE, &acl.acl, FALSE);
2167 InitializeObjectAttributes(&attr, NULL, 0, NULL, &sd);
2168 status = NtCreateDebugObject(&debug_obj, MAXIMUM_ALLOWED, &attr, DEBUG_KILL_ON_CLOSE);
2169 ok(SUCCEEDED(status), "Failed to create debug object: %#010lx\n", status);
2170 if (FAILED(status)) return;
2172 old_debug_obj = pDbgUiGetThreadDebugObject();
2173 pDbgUiSetThreadDebugObject(debug_obj);
2175 sprintf(cmdline, "%s %s %s %lu", argv[0], argv[1], "debuggee:dbgport", access);
2177 memset(&si, 0, sizeof(si));
2178 si.cb = sizeof(si);
2179 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE,
2180 DEBUG_PROCESS, NULL, NULL, &si, &pi);
2181 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2182 if (!ret) goto close_debug_obj;
2186 ret = WaitForDebugEvent(&ev, INFINITE);
2187 ok(ret, "WaitForDebugEvent failed, last error %#lx.\n", GetLastError());
2188 if (!ret) break;
2190 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
2191 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
2192 if (!ret) break;
2193 } while (ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
2195 wait_child_process(pi.hProcess);
2196 ret = CloseHandle(pi.hThread);
2197 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2198 ret = CloseHandle(pi.hProcess);
2199 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2201 close_debug_obj:
2202 pDbgUiSetThreadDebugObject(old_debug_obj);
2203 NtClose(debug_obj);
2206 static TOKEN_OWNER *get_current_owner(void)
2208 TOKEN_OWNER *owner;
2209 ULONG length = 0;
2210 HANDLE token;
2211 BOOL ret;
2213 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token);
2214 ok(ret, "Failed to get process token: %lu\n", GetLastError());
2216 ret = GetTokenInformation(token, TokenOwner, NULL, 0, &length);
2217 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2218 "GetTokenInformation failed: %lu\n", GetLastError());
2219 ok(length != 0, "Failed to get token owner information length: %lu\n", GetLastError());
2221 owner = HeapAlloc(GetProcessHeap(), 0, length);
2222 ret = GetTokenInformation(token, TokenOwner, owner, length, &length);
2223 ok(ret, "Failed to get token owner information: %lu)\n", GetLastError());
2225 CloseHandle(token);
2226 return owner;
2229 static void test_query_process_debug_port_custom_dacl(int argc, char **argv)
2231 static const ACCESS_MASK all_access_masks[] = {
2232 GENERIC_ALL,
2233 DEBUG_ALL_ACCESS,
2234 STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE,
2236 TOKEN_OWNER *owner;
2237 int i;
2239 if (!pDbgUiSetThreadDebugObject)
2241 win_skip("DbgUiGetThreadDebugObject not found\n");
2242 return;
2245 if (!pDbgUiGetThreadDebugObject)
2247 win_skip("DbgUiSetThreadDebugObject not found\n");
2248 return;
2251 owner = get_current_owner();
2253 for (i = 0; i < ARRAY_SIZE(all_access_masks); i++)
2255 ACCESS_MASK access = all_access_masks[i];
2257 winetest_push_context("debug object access %08lx", access);
2258 subtest_query_process_debug_port_custom_dacl(argc, argv, access, owner->Owner);
2259 winetest_pop_context();
2262 HeapFree(GetProcessHeap(), 0, owner);
2265 static void test_query_process_priority(void)
2267 PROCESS_PRIORITY_CLASS priority[2];
2268 ULONG ReturnLength;
2269 DWORD orig_priority;
2270 NTSTATUS status;
2271 BOOL ret;
2273 status = NtQueryInformationProcess(NULL, ProcessPriorityClass, NULL, sizeof(priority[0]), NULL);
2274 ok(status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_HANDLE) /* w2k3 */,
2275 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
2277 status = NtQueryInformationProcess(NULL, ProcessPriorityClass, &priority, sizeof(priority[0]), NULL);
2278 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2280 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, 1, &ReturnLength);
2281 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2283 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority), &ReturnLength);
2284 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2286 orig_priority = GetPriorityClass(GetCurrentProcess());
2287 ret = SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
2288 ok(ret, "Failed to set priority class: %lu\n", GetLastError());
2290 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority[0]), &ReturnLength);
2291 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2292 ok(priority[0].PriorityClass == PROCESS_PRIOCLASS_BELOW_NORMAL,
2293 "Expected PROCESS_PRIOCLASS_BELOW_NORMAL, got %u\n", priority[0].PriorityClass);
2295 ret = SetPriorityClass(GetCurrentProcess(), orig_priority);
2296 ok(ret, "Failed to reset priority class: %lu\n", GetLastError());
2299 static void test_query_process_handlecount(void)
2301 NTSTATUS status;
2302 ULONG ReturnLength;
2303 DWORD handlecount;
2304 BYTE buffer[2 * sizeof(DWORD)];
2305 HANDLE process;
2307 status = NtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
2308 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
2309 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08lx\n", status);
2311 status = NtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
2312 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2314 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
2315 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2317 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
2318 if (!process)
2320 trace("Could not open process with ID : %ld, error : %lu. Going to use current one.\n", one_before_last_pid, GetLastError());
2321 process = GetCurrentProcess();
2323 else
2324 if (winetest_debug > 1) trace("ProcessHandleCount for process with ID : %ld\n", one_before_last_pid);
2326 status = NtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
2327 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2328 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
2329 CloseHandle(process);
2331 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, buffer, sizeof(buffer), &ReturnLength);
2332 ok( status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_SUCCESS,
2333 "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08lx\n", status);
2334 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %ld\n", ReturnLength);
2336 /* Check if we have some return values */
2337 if (winetest_debug > 1) trace("HandleCount : %ld\n", handlecount);
2338 todo_wine
2340 ok( handlecount > 0, "Expected some handles, got 0\n");
2344 static void test_query_process_image_file_name(void)
2346 static const WCHAR deviceW[] = {'\\','D','e','v','i','c','e','\\'};
2347 NTSTATUS status;
2348 ULONG ReturnLength;
2349 UNICODE_STRING image_file_name;
2350 UNICODE_STRING *buffer = NULL;
2352 status = NtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL);
2353 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2355 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength);
2356 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2358 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength);
2359 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2361 buffer = malloc(ReturnLength);
2362 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength);
2363 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2364 todo_wine
2365 ok(!memcmp(buffer->Buffer, deviceW, sizeof(deviceW)),
2366 "Expected image name to begin with \\Device\\, got %s\n",
2367 wine_dbgstr_wn(buffer->Buffer, buffer->Length / sizeof(WCHAR)));
2368 free(buffer);
2370 status = NtQueryInformationProcess(NULL, ProcessImageFileNameWin32, &image_file_name, sizeof(image_file_name), NULL);
2371 if (status == STATUS_INVALID_INFO_CLASS)
2373 win_skip("ProcessImageFileNameWin32 is not supported\n");
2374 return;
2376 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2378 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileNameWin32, &image_file_name, 2, &ReturnLength);
2379 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2381 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileNameWin32, &image_file_name, sizeof(image_file_name), &ReturnLength);
2382 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
2384 buffer = malloc(ReturnLength);
2385 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileNameWin32, buffer, ReturnLength, &ReturnLength);
2386 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2387 ok(memcmp(buffer->Buffer, deviceW, sizeof(deviceW)),
2388 "Expected image name not to begin with \\Device\\, got %s\n",
2389 wine_dbgstr_wn(buffer->Buffer, buffer->Length / sizeof(WCHAR)));
2390 free(buffer);
2393 static void test_query_process_image_info(void)
2395 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
2396 NTSTATUS status;
2397 SECTION_IMAGE_INFORMATION info;
2398 ULONG len;
2400 status = NtQueryInformationProcess( NULL, ProcessImageInformation, &info, sizeof(info), &len );
2401 ok( status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_PARAMETER), /* winxp */
2402 "got %08lx\n", status);
2404 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, &info, sizeof(info)-1, &len );
2405 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status);
2407 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, &info, sizeof(info)+1, &len );
2408 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status);
2410 memset( &info, 0xcc, sizeof(info) );
2411 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageInformation, &info, sizeof(info), &len );
2412 ok( status == STATUS_SUCCESS, "got %08lx\n", status);
2413 ok( len == sizeof(info), "wrong len %lu\n", len );
2415 ok( info.MajorSubsystemVersion == nt->OptionalHeader.MajorSubsystemVersion,
2416 "wrong major version %x/%x\n",
2417 info.MajorSubsystemVersion, nt->OptionalHeader.MajorSubsystemVersion );
2418 ok( info.MinorSubsystemVersion == nt->OptionalHeader.MinorSubsystemVersion,
2419 "wrong minor version %x/%x\n",
2420 info.MinorSubsystemVersion, nt->OptionalHeader.MinorSubsystemVersion );
2421 ok( info.MajorOperatingSystemVersion == nt->OptionalHeader.MajorOperatingSystemVersion ||
2422 broken( !info.MajorOperatingSystemVersion ), /* <= win8 */
2423 "wrong major OS version %x/%x\n",
2424 info.MajorOperatingSystemVersion, nt->OptionalHeader.MajorOperatingSystemVersion );
2425 ok( info.MinorOperatingSystemVersion == nt->OptionalHeader.MinorOperatingSystemVersion,
2426 "wrong minor OS version %x/%x\n",
2427 info.MinorOperatingSystemVersion, nt->OptionalHeader.MinorOperatingSystemVersion );
2430 static void test_query_process_debug_object_handle(int argc, char **argv)
2432 char cmdline[MAX_PATH];
2433 STARTUPINFOA si = {0};
2434 PROCESS_INFORMATION pi;
2435 BOOL ret;
2436 HANDLE debug_object;
2437 NTSTATUS status;
2438 ULONG len;
2440 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
2442 si.cb = sizeof(si);
2443 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL,
2444 NULL, &si, &pi);
2445 ok(ret, "CreateProcess failed with last error %lu\n", GetLastError());
2446 if (!ret) return;
2448 len = 0xdeadbeef;
2449 status = NtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL, 0, &len);
2450 ok(status == STATUS_INFO_LENGTH_MISMATCH,
2451 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08lx\n",
2452 status);
2453 ok(len == 0xdeadbeef || broken(len == 0xfffffffc || len == 0xffc), /* wow64 */
2454 "len set to %lx\n", len );
2456 len = 0xdeadbeef;
2457 status = NtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL, sizeof(debug_object), &len);
2458 ok(status == STATUS_INVALID_HANDLE ||
2459 status == STATUS_ACCESS_VIOLATION, /* XP */
2460 "Expected NtQueryInformationProcess to return STATUS_INVALID_HANDLE, got 0x%08lx\n", status);
2461 ok(len == 0xdeadbeef || broken(len == 0xfffffffc || len == 0xffc), /* wow64 */
2462 "len set to %lx\n", len );
2464 status = NtQueryInformationProcess(GetCurrentProcess(),
2465 ProcessDebugObjectHandle, NULL, sizeof(debug_object), &len);
2466 ok(status == STATUS_ACCESS_VIOLATION,
2467 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08lx\n", status);
2468 ok(len == 0xdeadbeef || broken(len == 0xfffffffc || len == 0xffc), /* wow64 */
2469 "len set to %lx\n", len );
2471 status = NtQueryInformationProcess(NULL, ProcessDebugObjectHandle,
2472 &debug_object, sizeof(debug_object), NULL);
2473 ok(status == STATUS_INVALID_HANDLE,
2474 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08lx\n", status);
2476 len = 0xdeadbeef;
2477 status = NtQueryInformationProcess(GetCurrentProcess(),
2478 ProcessDebugObjectHandle, &debug_object, sizeof(debug_object) - 1, &len);
2479 ok(status == STATUS_INFO_LENGTH_MISMATCH,
2480 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08lx\n", status);
2481 ok(len == 0xdeadbeef || broken(len == 0xfffffffc || len == 0xffc), /* wow64 */
2482 "len set to %lx\n", len );
2484 len = 0xdeadbeef;
2485 status = NtQueryInformationProcess(GetCurrentProcess(),
2486 ProcessDebugObjectHandle, &debug_object, sizeof(debug_object) + 1, &len);
2487 ok(status == STATUS_INFO_LENGTH_MISMATCH,
2488 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08lx\n", status);
2489 ok(len == 0xdeadbeef || broken(len == 0xfffffffc || len == 0xffc), /* wow64 */
2490 "len set to %lx\n", len );
2492 len = 0xdeadbeef;
2493 debug_object = (HANDLE)0xdeadbeef;
2494 status = NtQueryInformationProcess(GetCurrentProcess(),
2495 ProcessDebugObjectHandle, &debug_object,
2496 sizeof(debug_object), &len);
2497 ok(status == STATUS_PORT_NOT_SET,
2498 "Expected NtQueryInformationProcess to return STATUS_PORT_NOT_SET, got 0x%08lx\n", status);
2499 ok(debug_object == NULL ||
2500 broken(debug_object == (HANDLE)0xdeadbeef), /* Wow64 */
2501 "Expected debug object handle to be NULL, got %p\n", debug_object);
2502 ok(len == sizeof(debug_object), "len set to %lx\n", len );
2504 len = 0xdeadbeef;
2505 debug_object = (HANDLE)0xdeadbeef;
2506 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle,
2507 &debug_object, sizeof(debug_object), &len);
2508 ok(status == STATUS_SUCCESS,
2509 "Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08lx\n", status);
2510 ok(debug_object != NULL,
2511 "Expected debug object handle to be non-NULL, got %p\n", debug_object);
2512 ok(len == sizeof(debug_object), "len set to %lx\n", len );
2513 status = NtClose( debug_object );
2514 ok( !status, "NtClose failed %lx\n", status );
2516 for (;;)
2518 DEBUG_EVENT ev;
2520 ret = WaitForDebugEvent(&ev, INFINITE);
2521 ok(ret, "WaitForDebugEvent failed with last error %lu\n", GetLastError());
2522 if (!ret) break;
2524 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
2526 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
2527 ok(ret, "ContinueDebugEvent failed with last error %lu\n", GetLastError());
2528 if (!ret) break;
2531 ret = CloseHandle(pi.hThread);
2532 ok(ret, "CloseHandle failed with last error %lu\n", GetLastError());
2533 ret = CloseHandle(pi.hProcess);
2534 ok(ret, "CloseHandle failed with last error %lu\n", GetLastError());
2537 static void test_query_process_debug_flags(int argc, char **argv)
2539 static const DWORD test_flags[] = { DEBUG_PROCESS,
2540 DEBUG_ONLY_THIS_PROCESS,
2541 DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
2542 CREATE_SUSPENDED };
2543 DWORD debug_flags = 0xdeadbeef;
2544 char cmdline[MAX_PATH];
2545 PROCESS_INFORMATION pi;
2546 STARTUPINFOA si = { 0 };
2547 NTSTATUS status;
2548 DEBUG_EVENT ev;
2549 DWORD result;
2550 BOOL ret;
2551 int i, j;
2553 /* test invalid arguments */
2554 status = NtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, 0, NULL);
2555 ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
2556 "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2558 status = NtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, sizeof(debug_flags), NULL);
2559 ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
2560 "Expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
2562 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
2563 NULL, sizeof(debug_flags), NULL);
2564 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#lx.\n", status);
2566 status = NtQueryInformationProcess(NULL, ProcessDebugFlags,
2567 &debug_flags, sizeof(debug_flags), NULL);
2568 ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
2569 "Expected STATUS_INVALID_HANDLE, got %#lx.\n", status);
2571 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
2572 &debug_flags, sizeof(debug_flags) - 1, NULL);
2573 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2575 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
2576 &debug_flags, sizeof(debug_flags) + 1, NULL);
2577 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx.\n", status);
2579 /* test ProcessDebugFlags of current process */
2580 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
2581 &debug_flags, sizeof(debug_flags), NULL);
2582 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2583 ok(debug_flags == TRUE, "Expected flag TRUE, got %lx.\n", debug_flags);
2585 for (i = 0; i < ARRAY_SIZE(test_flags); i++)
2587 DWORD expected_flags = !(test_flags[i] & DEBUG_ONLY_THIS_PROCESS);
2588 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
2590 si.cb = sizeof(si);
2591 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, test_flags[i], NULL, NULL, &si, &pi);
2592 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2594 if (!(test_flags[i] & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)))
2596 /* test ProcessDebugFlags before attaching with debugger */
2597 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
2598 &debug_flags, sizeof(debug_flags), NULL);
2599 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2600 ok(debug_flags == TRUE, "Expected flag TRUE, got %lx.\n", debug_flags);
2602 ret = DebugActiveProcess(pi.dwProcessId);
2603 ok(ret, "DebugActiveProcess failed, last error %#lx.\n", GetLastError());
2604 expected_flags = FALSE;
2607 /* test ProcessDebugFlags after attaching with debugger */
2608 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
2609 &debug_flags, sizeof(debug_flags), NULL);
2610 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2611 ok(debug_flags == expected_flags, "Expected flag %lx, got %lx.\n", expected_flags, debug_flags);
2613 if (!(test_flags[i] & CREATE_SUSPENDED))
2615 /* Continue a couple of times to make sure the process is fully initialized,
2616 * otherwise Windows XP deadlocks in the following DebugActiveProcess(). */
2617 for (;;)
2619 ret = WaitForDebugEvent(&ev, 1000);
2620 ok(ret, "WaitForDebugEvent failed, last error %#lx.\n", GetLastError());
2621 if (!ret) break;
2623 if (ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) break;
2625 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
2626 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
2627 if (!ret) break;
2630 result = SuspendThread(pi.hThread);
2631 ok(result == 0, "Expected 0, got %lu.\n", result);
2634 ret = DebugActiveProcessStop(pi.dwProcessId);
2635 ok(ret, "DebugActiveProcessStop failed, last error %#lx.\n", GetLastError());
2637 /* test ProcessDebugFlags after detaching debugger */
2638 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
2639 &debug_flags, sizeof(debug_flags), NULL);
2640 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2641 ok(debug_flags == expected_flags, "Expected flag %lx, got %lx.\n", expected_flags, debug_flags);
2643 ret = DebugActiveProcess(pi.dwProcessId);
2644 ok(ret, "DebugActiveProcess failed, last error %#lx.\n", GetLastError());
2646 /* test ProcessDebugFlags after re-attaching debugger */
2647 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
2648 &debug_flags, sizeof(debug_flags), NULL);
2649 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2650 ok(debug_flags == FALSE, "Expected flag FALSE, got %lx.\n", debug_flags);
2652 result = ResumeThread(pi.hThread);
2653 todo_wine ok(result == 2, "Expected 2, got %lu.\n", result);
2655 /* Wait until the process is terminated. On Windows XP the process randomly
2656 * gets stuck in a non-continuable exception, so stop after 100 iterations.
2657 * On Windows 2003, the debugged process disappears (or stops?) without
2658 * any EXIT_PROCESS_DEBUG_EVENT after a couple of events. */
2659 for (j = 0; j < 100; j++)
2661 ret = WaitForDebugEvent(&ev, 1000);
2662 ok(ret || broken(GetLastError() == ERROR_SEM_TIMEOUT),
2663 "WaitForDebugEvent failed, last error %#lx.\n", GetLastError());
2664 if (!ret) break;
2666 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
2668 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
2669 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
2670 if (!ret) break;
2672 ok(j < 100 || broken(j >= 100) /* Win XP */, "Expected less than 100 debug events.\n");
2674 /* test ProcessDebugFlags after process has terminated */
2675 status = NtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
2676 &debug_flags, sizeof(debug_flags), NULL);
2677 ok(!status, "NtQueryInformationProcess failed, status %#lx.\n", status);
2678 ok(debug_flags == FALSE, "Expected flag FALSE, got %lx.\n", debug_flags);
2680 ret = CloseHandle(pi.hThread);
2681 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2682 ret = CloseHandle(pi.hProcess);
2683 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
2687 static void test_query_process_quota_limits(void)
2689 QUOTA_LIMITS qlimits;
2690 NTSTATUS status;
2691 HANDLE process;
2692 ULONG ret_len;
2694 status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, NULL, sizeof(qlimits), NULL);
2695 ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status);
2697 status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, &qlimits, sizeof(qlimits), NULL);
2698 ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status);
2700 process = GetCurrentProcess();
2701 status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, 2, &ret_len);
2702 ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status);
2704 memset(&qlimits, 0, sizeof(qlimits));
2705 status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits), &ret_len);
2706 ok(status == STATUS_SUCCESS, "NtQueryInformationProcess failed, status %#lx.\n", status);
2707 ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len);
2708 ok(qlimits.MinimumWorkingSetSize == 204800,"Expected MinimumWorkingSetSize = 204800, got %s\n",
2709 wine_dbgstr_longlong(qlimits.MinimumWorkingSetSize));
2710 ok(qlimits.MaximumWorkingSetSize == 1413120,"Expected MaximumWorkingSetSize = 1413120, got %s\n",
2711 wine_dbgstr_longlong(qlimits.MaximumWorkingSetSize));
2712 ok(qlimits.PagefileLimit == ~0,"Expected PagefileLimit = ~0, got %s\n",
2713 wine_dbgstr_longlong(qlimits.PagefileLimit));
2714 ok(qlimits.TimeLimit.QuadPart == ~0,"Expected TimeLimit = ~0, got %s\n",
2715 wine_dbgstr_longlong(qlimits.TimeLimit.QuadPart));
2717 if (winetest_debug > 1)
2719 trace("Quota Limits:\n");
2720 trace("PagedPoolLimit: %s\n", wine_dbgstr_longlong(qlimits.PagedPoolLimit));
2721 trace("NonPagedPoolLimit: %s\n", wine_dbgstr_longlong(qlimits.NonPagedPoolLimit));
2724 memset(&qlimits, 0, sizeof(qlimits));
2725 status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits) * 2, &ret_len);
2726 ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status);
2727 ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len);
2729 memset(&qlimits, 0, sizeof(qlimits));
2730 status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits) - 1, &ret_len);
2731 ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status);
2732 ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len);
2734 memset(&qlimits, 0, sizeof(qlimits));
2735 status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits) + 1, &ret_len);
2736 ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status);
2737 ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len);
2740 static void test_readvirtualmemory(void)
2742 HANDLE process;
2743 NTSTATUS status;
2744 SIZE_T readcount;
2745 static const char teststring[] = "test string";
2746 char buffer[12];
2748 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
2749 ok(process != 0, "Expected to be able to open own process for reading memory\n");
2751 /* normal operation */
2752 status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
2753 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2754 ok( readcount == 12, "Expected to read 12 bytes, got %Id\n",readcount);
2755 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
2757 /* no number of bytes */
2758 memset(buffer, 0, 12);
2759 status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
2760 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2761 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
2763 /* illegal remote address */
2764 todo_wine{
2765 status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
2766 ok( status == STATUS_PARTIAL_COPY, "Expected STATUS_PARTIAL_COPY, got %08lx\n", status);
2767 if (status == STATUS_PARTIAL_COPY)
2768 ok( readcount == 0, "Expected to read 0 bytes, got %Id\n",readcount);
2771 /* 0 handle */
2772 status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
2773 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status);
2774 ok( readcount == 0, "Expected to read 0 bytes, got %Id\n",readcount);
2776 /* pseudo handle for current process*/
2777 memset(buffer, 0, 12);
2778 status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
2779 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2780 ok( readcount == 12, "Expected to read 12 bytes, got %Id\n",readcount);
2781 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
2783 /* illegal local address */
2784 status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
2785 ok( status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_PARTIAL_COPY) /* Win10 */,
2786 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
2787 if (status == STATUS_ACCESS_VIOLATION)
2788 ok( readcount == 0, "Expected to read 0 bytes, got %Id\n",readcount);
2790 CloseHandle(process);
2793 static void test_mapprotection(void)
2795 HANDLE h;
2796 void* addr;
2797 MEMORY_BASIC_INFORMATION info;
2798 ULONG oldflags, flagsize, flags = MEM_EXECUTE_OPTION_ENABLE;
2799 LARGE_INTEGER size, offset;
2800 NTSTATUS status;
2801 SIZE_T retlen, count;
2802 void (*f)(void);
2803 BOOL reset_flags = FALSE;
2805 /* Switch to being a noexec unaware process */
2806 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof (oldflags), &flagsize);
2807 if (status == STATUS_INVALID_PARAMETER)
2809 skip("Unable to query process execute flags on this platform\n");
2810 return;
2812 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
2813 if (winetest_debug > 1) trace("Process execute flags %08lx\n", oldflags);
2815 if (!(oldflags & MEM_EXECUTE_OPTION_ENABLE))
2817 if (oldflags & MEM_EXECUTE_OPTION_PERMANENT)
2819 skip("Unable to turn off noexec\n");
2820 return;
2823 if (pGetSystemDEPPolicy && pGetSystemDEPPolicy() == AlwaysOn)
2825 skip("System policy requires noexec\n");
2826 return;
2829 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
2830 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
2831 reset_flags = TRUE;
2834 size.u.LowPart = 0x2000;
2835 size.u.HighPart = 0;
2836 status = pNtCreateSection ( &h,
2837 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
2838 NULL,
2839 &size,
2840 PAGE_READWRITE,
2841 SEC_COMMIT | SEC_NOCACHE,
2844 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2846 offset.u.LowPart = 0;
2847 offset.u.HighPart = 0;
2848 count = 0x2000;
2849 addr = NULL;
2850 status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
2851 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2853 #if defined(__x86_64__) || defined(__i386__)
2854 *(unsigned char*)addr = 0xc3; /* lret ... in both i386 and x86_64 */
2855 #elif defined(__arm__)
2856 *(unsigned long*)addr = 0xe12fff1e; /* bx lr */
2857 #elif defined(__aarch64__)
2858 *(unsigned long*)addr = 0xd65f03c0; /* ret */
2859 #else
2860 ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
2861 #endif
2862 if (winetest_debug > 1) trace("trying to execute code in the readwrite only mapped anon file...\n");
2863 f = addr;f();
2864 if (winetest_debug > 1) trace("...done.\n");
2866 status = pNtQueryVirtualMemory( GetCurrentProcess(), addr, MemoryBasicInformation, &info, sizeof(info), &retlen );
2867 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2868 ok( retlen == sizeof(info), "Expected STATUS_SUCCESS, got %08lx\n", status);
2869 ok((info.Protect & ~PAGE_NOCACHE) == PAGE_READWRITE, "addr.Protect is not PAGE_READWRITE, but 0x%lx\n", info.Protect);
2871 status = pNtUnmapViewOfSection( GetCurrentProcess(), (char *)addr + 0x1050 );
2872 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2873 pNtClose (h);
2875 if (reset_flags)
2876 pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof(oldflags) );
2879 static void test_threadstack(void)
2881 PROCESS_STACK_ALLOCATION_INFORMATION info = { 0x100000, 0, (void *)0xdeadbeef };
2882 PROCESS_STACK_ALLOCATION_INFORMATION_EX info_ex = { 0 };
2883 MEMORY_BASIC_INFORMATION meminfo;
2884 SIZE_T retlen;
2885 NTSTATUS status;
2887 info.ReserveSize = 0x100000;
2888 info.StackBase = (void *)0xdeadbeef;
2889 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, &info, sizeof(info) );
2890 ok( !status, "NtSetInformationProcess failed %08lx\n", status );
2891 ok( info.StackBase != (void *)0xdeadbeef, "stackbase not set\n" );
2893 status = pNtQueryVirtualMemory( GetCurrentProcess(), info.StackBase, MemoryBasicInformation,
2894 &meminfo, sizeof(meminfo), &retlen );
2895 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2896 ok( retlen == sizeof(meminfo), "Expected STATUS_SUCCESS, got %08lx\n", status);
2897 ok( meminfo.AllocationBase == info.StackBase, "wrong base %p/%p\n",
2898 meminfo.AllocationBase, info.StackBase );
2899 ok( meminfo.RegionSize == info.ReserveSize, "wrong size %Ix/%Ix\n",
2900 meminfo.RegionSize, info.ReserveSize );
2901 ok( meminfo.State == MEM_RESERVE, "wrong state %lx\n", meminfo.State );
2902 ok( meminfo.Protect == 0, "wrong protect %lx\n", meminfo.Protect );
2903 ok( meminfo.Type == MEM_PRIVATE, "wrong type %lx\n", meminfo.Type );
2905 info_ex.AllocInfo = info;
2906 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation,
2907 &info_ex, sizeof(info_ex) );
2908 if (status != STATUS_INVALID_PARAMETER)
2910 ok( !status, "NtSetInformationProcess failed %08lx\n", status );
2911 ok( info_ex.AllocInfo.StackBase != info.StackBase, "stackbase not set\n" );
2912 status = pNtQueryVirtualMemory( GetCurrentProcess(), info_ex.AllocInfo.StackBase,
2913 MemoryBasicInformation, &meminfo, sizeof(meminfo), &retlen );
2914 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2915 ok( retlen == sizeof(meminfo), "Expected STATUS_SUCCESS, got %08lx\n", status);
2916 ok( meminfo.AllocationBase == info_ex.AllocInfo.StackBase, "wrong base %p/%p\n",
2917 meminfo.AllocationBase, info_ex.AllocInfo.StackBase );
2918 ok( meminfo.RegionSize == info_ex.AllocInfo.ReserveSize, "wrong size %Ix/%Ix\n",
2919 meminfo.RegionSize, info_ex.AllocInfo.ReserveSize );
2920 ok( meminfo.State == MEM_RESERVE, "wrong state %lx\n", meminfo.State );
2921 ok( meminfo.Protect == 0, "wrong protect %lx\n", meminfo.Protect );
2922 ok( meminfo.Type == MEM_PRIVATE, "wrong type %lx\n", meminfo.Type );
2923 VirtualFree( info_ex.AllocInfo.StackBase, 0, MEM_FREE );
2924 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation,
2925 &info, sizeof(info) - 1 );
2926 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08lx\n", status );
2927 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation,
2928 &info, sizeof(info) + 1 );
2929 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08lx\n", status );
2930 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation,
2931 &info_ex, sizeof(info_ex) - 1 );
2932 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08lx\n", status );
2933 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation,
2934 &info_ex, sizeof(info_ex) + 1 );
2935 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08lx\n", status );
2937 else win_skip( "ProcessThreadStackAllocation ex not supported\n" );
2939 VirtualFree( info.StackBase, 0, MEM_FREE );
2942 static void test_queryvirtualmemory(void)
2944 NTSTATUS status;
2945 SIZE_T readcount, prev;
2946 static const char teststring[] = "test string";
2947 static char datatestbuf[42] = "abc";
2948 static char rwtestbuf[42];
2949 MEMORY_BASIC_INFORMATION mbi;
2950 char stackbuf[42];
2951 HMODULE module;
2952 void *user_shared_data = (void *)0x7ffe0000;
2953 void *buffer[256];
2954 MEMORY_SECTION_NAME *name = (MEMORY_SECTION_NAME *)buffer;
2955 SYSTEM_BASIC_INFORMATION sbi;
2957 module = GetModuleHandleA( "ntdll.dll" );
2958 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
2959 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2960 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
2961 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
2962 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
2963 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%x\n", mbi.State, MEM_COMMIT);
2964 ok (mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%lx, expected 0x%x\n", mbi.Protect, PAGE_READONLY);
2965 ok (mbi.Type == MEM_IMAGE, "mbi.Type is 0x%lx, expected 0x%x\n", mbi.Type, MEM_IMAGE);
2967 module = GetModuleHandleA( "ntdll.dll" );
2968 status = pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
2969 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2970 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
2971 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
2972 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
2973 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%x\n", mbi.State, MEM_COMMIT);
2974 ok (mbi.Protect == PAGE_EXECUTE_READ, "mbi.Protect is 0x%lx, expected 0x%x\n", mbi.Protect, PAGE_EXECUTE_READ);
2976 status = pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
2977 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2978 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
2979 ok (mbi.AllocationProtect == PAGE_READWRITE || mbi.AllocationProtect == PAGE_EXECUTE_READWRITE,
2980 "mbi.AllocationProtect is 0x%lx\n", mbi.AllocationProtect);
2981 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%x\n", mbi.State, MEM_COMMIT);
2982 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE,
2983 "mbi.Protect is 0x%lx\n", mbi.Protect);
2985 status = pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
2986 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2987 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
2988 ok (mbi.AllocationProtect == PAGE_READWRITE, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_READWRITE);
2989 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%x\n", mbi.State, MEM_COMMIT);
2990 ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%lx, expected 0x%x\n", mbi.Protect, PAGE_READWRITE);
2992 module = GetModuleHandleA( NULL );
2993 status = pNtQueryVirtualMemory(NtCurrentProcess(), teststring, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
2994 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
2995 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
2996 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
2997 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
2998 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%X\n", mbi.State, MEM_COMMIT);
2999 ok (mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%lx, expected 0x%X\n", mbi.Protect, PAGE_READONLY);
3001 status = pNtQueryVirtualMemory(NtCurrentProcess(), datatestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
3002 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3003 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
3004 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
3005 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
3006 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%X\n", mbi.State, MEM_COMMIT);
3007 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY,
3008 "mbi.Protect is 0x%lx\n", mbi.Protect);
3010 status = pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
3011 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3012 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
3013 if (mbi.AllocationBase == module)
3015 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
3016 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%X\n", mbi.State, MEM_COMMIT);
3017 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY,
3018 "mbi.Protect is 0x%lx\n", mbi.Protect);
3020 else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
3022 status = pNtQueryVirtualMemory(NtCurrentProcess(), user_shared_data, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
3023 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3024 ok(readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %Id\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
3025 ok(mbi.AllocationBase == user_shared_data, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, user_shared_data);
3026 ok(mbi.AllocationProtect == PAGE_READONLY, "mbi.AllocationProtect is 0x%lx, expected 0x%x\n", mbi.AllocationProtect, PAGE_READONLY);
3027 ok(mbi.State == MEM_COMMIT, "mbi.State is 0x%lx, expected 0x%X\n", mbi.State, MEM_COMMIT);
3028 ok(mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%lx\n", mbi.Protect);
3029 ok(mbi.Type == MEM_PRIVATE, "mbi.Type is 0x%lx, expected 0x%x\n", mbi.Type, MEM_PRIVATE);
3030 ok(mbi.RegionSize == 0x1000, "mbi.RegionSize is 0x%Ix, expected 0x%x\n", mbi.RegionSize, 0x1000);
3032 /* check error code when addr is higher than user space limit */
3033 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
3034 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3035 status = pNtQueryVirtualMemory(NtCurrentProcess(), sbi.LowestUserAddress, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
3036 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3037 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)sbi.LowestUserAddress-1, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
3038 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3039 status = pNtQueryVirtualMemory(NtCurrentProcess(), sbi.HighestUserAddress, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
3040 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3041 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)sbi.HighestUserAddress+1, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
3042 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3043 status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)~0, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
3044 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3046 /* check error code when len is less than MEMORY_BASIC_INFORMATION size */
3047 status = pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION) - 1, &readcount);
3048 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status);
3050 module = GetModuleHandleA( "ntdll.dll" );
3051 memset(buffer, 0xcc, sizeof(buffer));
3052 readcount = 0xdeadbeef;
3053 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemoryMappedFilenameInformation,
3054 name, sizeof(*name) + 16, &readcount);
3055 ok(status == STATUS_BUFFER_OVERFLOW, "got %08lx\n", status);
3056 ok(name->SectionFileName.Length == 0xcccc || broken(!name->SectionFileName.Length), /* vista64 */
3057 "Wrong len %u\n", name->SectionFileName.Length);
3058 ok(readcount > sizeof(*name), "Wrong count %Iu\n", readcount);
3060 memset(buffer, 0xcc, sizeof(buffer));
3061 readcount = 0xdeadbeef;
3062 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)module + 1234, MemoryMappedFilenameInformation,
3063 name, sizeof(buffer), &readcount);
3064 ok(status == STATUS_SUCCESS, "got %08lx\n", status);
3065 ok(name->SectionFileName.Buffer == (WCHAR *)(name + 1), "Wrong ptr %p/%p\n",
3066 name->SectionFileName.Buffer, name + 1 );
3067 ok(name->SectionFileName.Length != 0xcccc, "Wrong len %u\n", name->SectionFileName.Length);
3068 ok(name->SectionFileName.MaximumLength == name->SectionFileName.Length + sizeof(WCHAR),
3069 "Wrong maxlen %u/%u\n", name->SectionFileName.MaximumLength, name->SectionFileName.Length);
3070 ok(readcount == sizeof(name->SectionFileName) + name->SectionFileName.MaximumLength,
3071 "Wrong count %Iu/%u\n", readcount, name->SectionFileName.MaximumLength);
3072 ok( !name->SectionFileName.Buffer[name->SectionFileName.Length / sizeof(WCHAR)],
3073 "buffer not null-terminated\n" );
3075 memset(buffer, 0xcc, sizeof(buffer));
3076 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)module + 1234, MemoryMappedFilenameInformation,
3077 name, sizeof(buffer), NULL);
3078 ok(status == STATUS_SUCCESS, "got %08lx\n", status);
3080 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)module + 1234, MemoryMappedFilenameInformation,
3081 NULL, sizeof(buffer), NULL);
3082 ok(status == STATUS_ACCESS_VIOLATION, "got %08lx\n", status);
3084 memset(buffer, 0xcc, sizeof(buffer));
3085 prev = readcount;
3086 readcount = 0xdeadbeef;
3087 status = pNtQueryVirtualMemory(NtCurrentProcess(), (char *)module + 321, MemoryMappedFilenameInformation,
3088 name, sizeof(*name) - 1, &readcount);
3089 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %08lx\n", status);
3090 ok(name->SectionFileName.Length == 0xcccc, "Wrong len %u\n", name->SectionFileName.Length);
3091 ok(readcount == prev, "Wrong count %Iu\n", readcount);
3093 memset(buffer, 0xcc, sizeof(buffer));
3094 readcount = 0xdeadbeef;
3095 status = pNtQueryVirtualMemory((HANDLE)0xdead, (char *)module + 1234, MemoryMappedFilenameInformation,
3096 name, sizeof(buffer), &readcount);
3097 ok(status == STATUS_INVALID_HANDLE, "got %08lx\n", status);
3098 ok(readcount == 0xdeadbeef || broken(readcount == 1024 + sizeof(*name)), /* wow64 */
3099 "Wrong count %Iu\n", readcount);
3101 memset(buffer, 0xcc, sizeof(buffer));
3102 readcount = 0xdeadbeef;
3103 status = pNtQueryVirtualMemory(NtCurrentProcess(), buffer, MemoryMappedFilenameInformation,
3104 name, sizeof(buffer), &readcount);
3105 ok(status == STATUS_INVALID_ADDRESS, "got %08lx\n", status);
3106 ok(name->SectionFileName.Length == 0xcccc, "Wrong len %u\n", name->SectionFileName.Length);
3107 ok(readcount == 0xdeadbeef || broken(readcount == 1024 + sizeof(*name)), /* wow64 */
3108 "Wrong count %Iu\n", readcount);
3110 readcount = 0xdeadbeef;
3111 status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)0x1234, MemoryMappedFilenameInformation,
3112 name, sizeof(buffer), &readcount);
3113 ok(status == STATUS_INVALID_ADDRESS, "got %08lx\n", status);
3114 ok(name->SectionFileName.Length == 0xcccc, "Wrong len %u\n", name->SectionFileName.Length);
3115 ok(readcount == 0xdeadbeef || broken(readcount == 1024 + sizeof(*name)), /* wow64 */
3116 "Wrong count %Iu\n", readcount);
3118 readcount = 0xdeadbeef;
3119 status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)0x1234, MemoryMappedFilenameInformation,
3120 name, sizeof(*name) - 1, &readcount);
3121 ok(status == STATUS_INVALID_ADDRESS, "got %08lx\n", status);
3122 ok(name->SectionFileName.Length == 0xcccc, "Wrong len %u\n", name->SectionFileName.Length);
3123 ok(readcount == 0xdeadbeef || broken(readcount == 15), /* wow64 */
3124 "Wrong count %Iu\n", readcount);
3127 static void test_affinity(void)
3129 NTSTATUS status;
3130 PROCESS_BASIC_INFORMATION pbi;
3131 DWORD_PTR proc_affinity, thread_affinity;
3132 THREAD_BASIC_INFORMATION tbi;
3133 SYSTEM_INFO si;
3135 GetSystemInfo(&si);
3136 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
3137 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3138 proc_affinity = pbi.AffinityMask;
3139 ok( proc_affinity == get_affinity_mask( si.dwNumberOfProcessors ), "Unexpected process affinity\n" );
3140 if (si.dwNumberOfProcessors < 8 * sizeof(DWORD_PTR))
3142 proc_affinity = (DWORD_PTR)1 << si.dwNumberOfProcessors;
3143 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
3144 ok( status == STATUS_INVALID_PARAMETER,
3145 "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3147 proc_affinity = 0;
3148 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
3149 ok( status == STATUS_INVALID_PARAMETER,
3150 "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3152 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3153 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3154 ok( tbi.AffinityMask == get_affinity_mask( si.dwNumberOfProcessors ), "Unexpected thread affinity\n" );
3155 if (si.dwNumberOfProcessors < 8 * sizeof(DWORD_PTR))
3157 thread_affinity = (DWORD_PTR)1 << si.dwNumberOfProcessors;
3158 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3159 ok( status == STATUS_INVALID_PARAMETER,
3160 "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3162 thread_affinity = 0;
3163 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3164 ok( status == STATUS_INVALID_PARAMETER,
3165 "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3167 thread_affinity = 1;
3168 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3169 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3170 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3171 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3172 ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
3174 /* NOTE: Pre-Vista does not allow bits to be set that are higher than the highest set bit in process affinity mask */
3175 thread_affinity = (pbi.AffinityMask << 1) | pbi.AffinityMask;
3176 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3177 ok( broken(status == STATUS_INVALID_PARAMETER) || (status == STATUS_SUCCESS), "Expected STATUS_SUCCESS, got %08lx\n", status );
3178 if (status == STATUS_SUCCESS)
3180 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3181 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3182 ok( tbi.AffinityMask == pbi.AffinityMask, "Unexpected thread affinity. Expected %Ix, got %Ix\n", pbi.AffinityMask, tbi.AffinityMask );
3185 thread_affinity = ~(DWORD_PTR)0 - 1;
3186 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3187 ok( broken(status == STATUS_INVALID_PARAMETER) || (status == STATUS_SUCCESS), "Expected STATUS_SUCCESS, got %08lx\n", status );
3188 if (status == STATUS_SUCCESS)
3190 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3191 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3192 ok( tbi.AffinityMask == (pbi.AffinityMask & (~(DWORD_PTR)0 - 1)), "Unexpected thread affinity. Expected %Ix, got %Ix\n", pbi.AffinityMask & (~(DWORD_PTR)0 - 1), tbi.AffinityMask );
3195 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
3196 thread_affinity = ~(DWORD_PTR)0;
3197 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3198 ok( broken(status == STATUS_INVALID_PARAMETER) || status == STATUS_SUCCESS,
3199 "Expected STATUS_SUCCESS, got %08lx\n", status);
3201 if (si.dwNumberOfProcessors <= 1)
3203 skip("only one processor, skipping affinity testing\n");
3204 return;
3207 /* Test thread affinity mask resulting from "all processors" flag */
3208 if (status == STATUS_SUCCESS)
3210 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3211 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3212 ok( tbi.AffinityMask == get_affinity_mask( si.dwNumberOfProcessors ), "unexpected affinity %#Ix\n", tbi.AffinityMask );
3214 else
3215 skip("Cannot test thread affinity mask for 'all processors' flag\n");
3217 proc_affinity = 2;
3218 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
3219 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3220 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
3221 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3222 proc_affinity = pbi.AffinityMask;
3223 ok( proc_affinity == 2, "Unexpected process affinity\n" );
3224 /* Setting the process affinity changes the thread affinity to match */
3225 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3226 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3227 ok( tbi.AffinityMask == 2, "Unexpected thread affinity\n" );
3228 /* The thread affinity is restricted to the process affinity */
3229 thread_affinity = 1;
3230 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
3231 ok( status == STATUS_INVALID_PARAMETER,
3232 "Expected STATUS_INVALID_PARAMETER, got %08lx\n", status);
3234 proc_affinity = get_affinity_mask( si.dwNumberOfProcessors );
3235 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
3236 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3237 /* Resetting the process affinity also resets the thread affinity */
3238 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
3239 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3240 ok( tbi.AffinityMask == get_affinity_mask( si.dwNumberOfProcessors ),
3241 "Unexpected thread affinity\n" );
3244 static DWORD WINAPI hide_from_debugger_thread(void *arg)
3246 HANDLE stop_event = arg;
3247 WaitForSingleObject( stop_event, INFINITE );
3248 return 0;
3251 static void test_HideFromDebugger(void)
3253 NTSTATUS status;
3254 HANDLE thread, stop_event;
3255 ULONG dummy;
3257 dummy = 0;
3258 status = pNtSetInformationThread( GetCurrentThread(), ThreadHideFromDebugger, &dummy, sizeof(ULONG) );
3259 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3260 dummy = 0;
3261 status = pNtSetInformationThread( GetCurrentThread(), ThreadHideFromDebugger, &dummy, 1 );
3262 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3263 status = pNtSetInformationThread( (HANDLE)0xdeadbeef, ThreadHideFromDebugger, NULL, 0 );
3264 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status );
3265 status = pNtSetInformationThread( GetCurrentThread(), ThreadHideFromDebugger, NULL, 0 );
3266 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3267 dummy = 0;
3268 status = NtQueryInformationThread( GetCurrentThread(), ThreadHideFromDebugger, &dummy, sizeof(ULONG), NULL );
3269 if (status == STATUS_INVALID_INFO_CLASS)
3271 win_skip("ThreadHideFromDebugger not available\n");
3272 return;
3275 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3276 dummy = 0;
3277 status = NtQueryInformationThread( (HANDLE)0xdeadbeef, ThreadHideFromDebugger, &dummy, sizeof(ULONG), NULL );
3278 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3279 dummy = 0;
3280 status = NtQueryInformationThread( GetCurrentThread(), ThreadHideFromDebugger, &dummy, 1, NULL );
3281 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3282 ok( dummy == 1, "Expected dummy == 1, got %08lx\n", dummy );
3284 stop_event = CreateEventA( NULL, FALSE, FALSE, NULL );
3285 ok( stop_event != NULL, "CreateEvent failed\n" );
3286 thread = CreateThread( NULL, 0, hide_from_debugger_thread, stop_event, 0, NULL );
3287 ok( thread != INVALID_HANDLE_VALUE, "CreateThread failed with %ld\n", GetLastError() );
3289 dummy = 0;
3290 status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
3291 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3292 ok( dummy == 0, "Expected dummy == 0, got %08lx\n", dummy );
3294 status = pNtSetInformationThread( thread, ThreadHideFromDebugger, NULL, 0 );
3295 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3297 dummy = 0;
3298 status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
3299 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3300 ok( dummy == 1, "Expected dummy == 1, got %08lx\n", dummy );
3302 SetEvent( stop_event );
3303 WaitForSingleObject( thread, INFINITE );
3304 CloseHandle( thread );
3305 CloseHandle( stop_event );
3308 static void test_NtGetCurrentProcessorNumber(void)
3310 NTSTATUS status;
3311 SYSTEM_INFO si;
3312 PROCESS_BASIC_INFORMATION pbi;
3313 THREAD_BASIC_INFORMATION tbi;
3314 DWORD_PTR old_process_mask;
3315 DWORD_PTR old_thread_mask;
3316 DWORD_PTR new_mask;
3317 ULONG current_cpu;
3318 ULONG i;
3320 if (!pNtGetCurrentProcessorNumber) {
3321 win_skip("NtGetCurrentProcessorNumber not available\n");
3322 return;
3325 GetSystemInfo(&si);
3326 current_cpu = pNtGetCurrentProcessorNumber();
3327 if (winetest_debug > 1) trace("dwNumberOfProcessors: %ld, current processor: %ld\n", si.dwNumberOfProcessors, current_cpu);
3329 status = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
3330 old_process_mask = pbi.AffinityMask;
3331 ok(status == STATUS_SUCCESS, "got 0x%lx (expected STATUS_SUCCESS)\n", status);
3333 status = pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
3334 old_thread_mask = tbi.AffinityMask;
3335 ok(status == STATUS_SUCCESS, "got 0x%lx (expected STATUS_SUCCESS)\n", status);
3337 /* allow the test to run on all processors */
3338 new_mask = get_affinity_mask( si.dwNumberOfProcessors );
3339 status = pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask, &new_mask, sizeof(new_mask));
3340 ok(status == STATUS_SUCCESS, "got 0x%lx (expected STATUS_SUCCESS)\n", status);
3342 for (i = 0; i < si.dwNumberOfProcessors; i++)
3344 new_mask = (DWORD_PTR)1 << i;
3345 status = pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &new_mask, sizeof(new_mask));
3346 ok(status == STATUS_SUCCESS, "%ld: got 0x%lx (expected STATUS_SUCCESS)\n", i, status);
3348 status = pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
3349 ok(status == STATUS_SUCCESS, "%ld: got 0x%lx (expected STATUS_SUCCESS)\n", i, status);
3351 current_cpu = pNtGetCurrentProcessorNumber();
3352 ok((current_cpu == i), "%ld (new_mask 0x%Ix): running on processor %ld (AffinityMask: 0x%Ix)\n",
3353 i, new_mask, current_cpu, tbi.AffinityMask);
3356 /* restore old values */
3357 status = pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask, &old_process_mask, sizeof(old_process_mask));
3358 ok(status == STATUS_SUCCESS, "got 0x%lx (expected STATUS_SUCCESS)\n", status);
3360 status = pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &old_thread_mask, sizeof(old_thread_mask));
3361 ok(status == STATUS_SUCCESS, "got 0x%lx (expected STATUS_SUCCESS)\n", status);
3364 static void test_ThreadEnableAlignmentFaultFixup(void)
3366 NTSTATUS status;
3367 ULONG dummy;
3369 dummy = 0;
3370 status = NtQueryInformationThread( GetCurrentThread(), ThreadEnableAlignmentFaultFixup, &dummy, sizeof(ULONG), NULL );
3371 ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status );
3372 status = NtQueryInformationThread( GetCurrentThread(), ThreadEnableAlignmentFaultFixup, &dummy, 1, NULL );
3373 ok( status == STATUS_INVALID_INFO_CLASS, "Expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status );
3375 dummy = 1;
3376 status = pNtSetInformationThread( GetCurrentThread(), ThreadEnableAlignmentFaultFixup, &dummy, sizeof(ULONG) );
3377 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3378 status = pNtSetInformationThread( (HANDLE)0xdeadbeef, ThreadEnableAlignmentFaultFixup, NULL, 0 );
3379 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3380 status = pNtSetInformationThread( (HANDLE)0xdeadbeef, ThreadEnableAlignmentFaultFixup, NULL, 1 );
3381 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status );
3382 status = pNtSetInformationThread( (HANDLE)0xdeadbeef, ThreadEnableAlignmentFaultFixup, &dummy, 1 );
3383 todo_wine ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08lx\n", status );
3384 status = pNtSetInformationThread( GetCurrentProcess(), ThreadEnableAlignmentFaultFixup, &dummy, 1 );
3385 todo_wine ok( status == STATUS_OBJECT_TYPE_MISMATCH, "Expected STATUS_OBJECT_TYPE_MISMATCH, got %08lx\n", status );
3386 dummy = 1;
3387 status = pNtSetInformationThread( GetCurrentThread(), ThreadEnableAlignmentFaultFixup, &dummy, 1 );
3388 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status );
3390 dummy = 0;
3391 status = pNtSetInformationThread( GetCurrentProcess(), ThreadEnableAlignmentFaultFixup, &dummy, 8 );
3392 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
3395 static DWORD WINAPI start_address_thread(void *arg)
3397 PRTL_THREAD_START_ROUTINE entry;
3398 NTSTATUS status;
3399 DWORD ret;
3401 entry = NULL;
3402 ret = 0xdeadbeef;
3403 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
3404 &entry, sizeof(entry), &ret);
3405 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3406 ok(ret == sizeof(entry), "NtQueryInformationThread returned %lu bytes\n", ret);
3407 ok(entry == (void *)start_address_thread, "expected %p, got %p\n", start_address_thread, entry);
3408 return 0;
3411 static void test_thread_start_address(void)
3413 PRTL_THREAD_START_ROUTINE entry, expected_entry;
3414 IMAGE_NT_HEADERS *nt;
3415 NTSTATUS status;
3416 HANDLE thread;
3417 void *module;
3418 DWORD ret;
3420 module = GetModuleHandleA(0);
3421 ok(module != NULL, "expected non-NULL address for module\n");
3422 nt = RtlImageNtHeader(module);
3423 ok(nt != NULL, "expected non-NULL address for NT header\n");
3425 entry = NULL;
3426 ret = 0xdeadbeef;
3427 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
3428 &entry, sizeof(entry), &ret);
3429 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3430 ok(ret == sizeof(entry), "NtQueryInformationThread returned %lu bytes\n", ret);
3431 expected_entry = (void *)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
3432 ok(entry == expected_entry, "expected %p, got %p\n", expected_entry, entry);
3434 entry = (void *)0xdeadbeef;
3435 status = pNtSetInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
3436 &entry, sizeof(entry));
3437 ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, /* >= Vista */
3438 "expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER, got %08lx\n", status);
3440 if (status == STATUS_SUCCESS)
3442 entry = NULL;
3443 ret = 0xdeadbeef;
3444 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
3445 &entry, sizeof(entry), &ret);
3446 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
3447 ok(ret == sizeof(entry), "NtQueryInformationThread returned %lu bytes\n", ret);
3448 ok(entry == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", entry);
3451 thread = CreateThread(NULL, 0, start_address_thread, NULL, 0, NULL);
3452 ok(thread != INVALID_HANDLE_VALUE, "CreateThread failed with %ld\n", GetLastError());
3453 ret = WaitForSingleObject(thread, 1000);
3454 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", ret);
3455 CloseHandle(thread);
3458 static void test_query_data_alignment(void)
3460 SYSTEM_CPU_INFORMATION sci;
3461 ULONG len;
3462 NTSTATUS status;
3463 DWORD value;
3465 value = 0xdeadbeef;
3466 status = pNtQuerySystemInformation(SystemRecommendedSharedDataAlignment, &value, sizeof(value), &len);
3467 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status);
3468 ok(sizeof(value) == len, "Inconsistent length %lu\n", len);
3470 pRtlGetNativeSystemInformation(SystemCpuInformation, &sci, sizeof(sci), &len);
3471 switch (sci.ProcessorArchitecture)
3473 case PROCESSOR_ARCHITECTURE_ARM:
3474 ok(value == 32, "Expected 32, got %lu\n", value);
3475 break;
3476 case PROCESSOR_ARCHITECTURE_ARM64:
3477 ok(value == 128, "Expected 128, got %lu\n", value);
3478 break;
3479 default:
3480 ok(value == 64, "Expected 64, got %lu\n", value);
3481 break;
3485 static void test_thread_lookup(void)
3487 OBJECT_BASIC_INFORMATION obj_info;
3488 THREAD_BASIC_INFORMATION info;
3489 OBJECT_ATTRIBUTES attr;
3490 CLIENT_ID cid;
3491 HANDLE handle;
3492 NTSTATUS status;
3494 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
3495 cid.UniqueProcess = ULongToHandle(GetCurrentProcessId());
3496 cid.UniqueThread = ULongToHandle(GetCurrentThreadId());
3497 status = pNtOpenThread(&handle, THREAD_QUERY_INFORMATION, &attr, &cid);
3498 ok(!status, "NtOpenThread returned %#lx\n", status);
3499 status = pNtOpenThread((HANDLE *)0xdeadbee0, THREAD_QUERY_INFORMATION, &attr, &cid);
3500 ok( status == STATUS_ACCESS_VIOLATION, "NtOpenThread returned %#lx\n", status);
3502 status = pNtQueryObject(handle, ObjectBasicInformation, &obj_info, sizeof(obj_info), NULL);
3503 ok(!status, "NtQueryObject returned: %#lx\n", status);
3504 ok(obj_info.GrantedAccess == (THREAD_QUERY_LIMITED_INFORMATION | THREAD_QUERY_INFORMATION)
3505 || broken(obj_info.GrantedAccess == THREAD_QUERY_INFORMATION), /* winxp */
3506 "GrantedAccess = %lx\n", obj_info.GrantedAccess);
3508 status = pNtQueryInformationThread(handle, ThreadBasicInformation, &info, sizeof(info), NULL);
3509 ok(!status, "NtQueryInformationThread returned %#lx\n", status);
3510 ok(info.ClientId.UniqueProcess == ULongToHandle(GetCurrentProcessId()),
3511 "UniqueProcess = %p expected %lx\n", info.ClientId.UniqueProcess, GetCurrentProcessId());
3512 ok(info.ClientId.UniqueThread == ULongToHandle(GetCurrentThreadId()),
3513 "UniqueThread = %p expected %lx\n", info.ClientId.UniqueThread, GetCurrentThreadId());
3514 pNtClose(handle);
3516 cid.UniqueProcess = 0;
3517 cid.UniqueThread = ULongToHandle(GetCurrentThreadId());
3518 status = pNtOpenThread(&handle, THREAD_QUERY_INFORMATION, &attr, &cid);
3519 ok(!status, "NtOpenThread returned %#lx\n", status);
3520 status = pNtQueryInformationThread(handle, ThreadBasicInformation, &info, sizeof(info), NULL);
3521 ok(!status, "NtQueryInformationThread returned %#lx\n", status);
3522 ok(info.ClientId.UniqueProcess == ULongToHandle(GetCurrentProcessId()),
3523 "UniqueProcess = %p expected %lx\n", info.ClientId.UniqueProcess, GetCurrentProcessId());
3524 ok(info.ClientId.UniqueThread == ULongToHandle(GetCurrentThreadId()),
3525 "UniqueThread = %p expected %lx\n", info.ClientId.UniqueThread, GetCurrentThreadId());
3526 pNtClose(handle);
3528 cid.UniqueProcess = ULongToHandle(0xdeadbeef);
3529 cid.UniqueThread = ULongToHandle(GetCurrentThreadId());
3530 handle = (HANDLE)0xdeadbeef;
3531 status = NtOpenThread(&handle, THREAD_QUERY_INFORMATION, &attr, &cid);
3532 todo_wine
3533 ok(status == STATUS_INVALID_CID, "NtOpenThread returned %#lx\n", status);
3534 todo_wine
3535 ok( !handle || broken(handle == (HANDLE)0xdeadbeef) /* vista */, "handle set %p\n", handle );
3536 if (!status) pNtClose(handle);
3538 cid.UniqueProcess = 0;
3539 cid.UniqueThread = ULongToHandle(0xdeadbeef);
3540 handle = (HANDLE)0xdeadbeef;
3541 status = pNtOpenThread(&handle, THREAD_QUERY_INFORMATION, &attr, &cid);
3542 ok(status == STATUS_INVALID_CID || broken(status == STATUS_INVALID_PARAMETER) /* winxp */,
3543 "NtOpenThread returned %#lx\n", status);
3544 ok( !handle || broken(handle == (HANDLE)0xdeadbeef) /* vista */, "handle set %p\n", handle );
3547 static void test_thread_ideal_processor(void)
3549 ULONG number, len;
3550 NTSTATUS status;
3552 number = 0;
3553 status = pNtSetInformationThread( GetCurrentThread(), ThreadIdealProcessor, &number, sizeof(number) );
3554 ok(NT_SUCCESS(status), "Unexpected status %#lx.\n", status);
3556 number = 64 + 1;
3557 status = pNtSetInformationThread( GetCurrentThread(), ThreadIdealProcessor, &number, sizeof(number) );
3558 ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#lx.\n", status);
3560 number = 0;
3561 status = pNtSetInformationThread( GetCurrentThread(), ThreadIdealProcessor, &number, sizeof(number) );
3562 ok(!status, "Unexpected status %#lx.\n", status);
3564 status = pNtQueryInformationThread( GetCurrentThread(), ThreadIdealProcessor, &number, sizeof(number), &len );
3565 ok(status == STATUS_INVALID_INFO_CLASS, "Unexpected status %#lx.\n", status);
3568 static void test_thread_info(void)
3570 NTSTATUS status;
3571 ULONG len, data;
3573 len = 0xdeadbeef;
3574 data = 0xcccccccc;
3575 status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
3576 &data, sizeof(data), &len );
3577 ok( !status, "failed %lx\n", status );
3578 ok( data == 0 || data == 1, "wrong data %lx\n", data );
3579 ok( len == sizeof(data), "wrong len %lu\n", len );
3581 len = 0xdeadbeef;
3582 data = 0xcccccccc;
3583 status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
3584 &data, sizeof(data) - 1, &len );
3585 ok( status == STATUS_INFO_LENGTH_MISMATCH, "failed %lx\n", status );
3586 ok( data == 0xcccccccc, "wrong data %lx\n", data );
3587 ok( len == 0xdeadbeef, "wrong len %lu\n", len );
3589 len = 0xdeadbeef;
3590 data = 0xcccccccc;
3591 status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
3592 &data, sizeof(data) + 1, &len );
3593 ok( status == STATUS_INFO_LENGTH_MISMATCH, "failed %lx\n", status );
3594 ok( data == 0xcccccccc, "wrong data %lx\n", data );
3595 ok( len == 0xdeadbeef, "wrong len %lu\n", len );
3598 static void test_debug_object(void)
3600 NTSTATUS status;
3601 HANDLE handle;
3602 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
3603 ULONG len, flag = 0;
3604 DBGUI_WAIT_STATE_CHANGE state;
3605 DEBUG_EVENT event;
3607 status = pNtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, 0 );
3608 ok( !status, "NtCreateDebugObject failed %lx\n", status );
3609 status = pNtSetInformationDebugObject( handle, 0, &flag, sizeof(ULONG), &len );
3610 ok( status == STATUS_INVALID_PARAMETER, "NtSetInformationDebugObject failed %lx\n", status );
3611 status = pNtSetInformationDebugObject( handle, 2, &flag, sizeof(ULONG), &len );
3612 ok( status == STATUS_INVALID_PARAMETER, "NtSetInformationDebugObject failed %lx\n", status );
3613 status = pNtSetInformationDebugObject( (HANDLE)0xdead, DebugObjectKillProcessOnExitInformation,
3614 &flag, sizeof(ULONG), &len );
3615 ok( status == STATUS_INVALID_HANDLE, "NtSetInformationDebugObject failed %lx\n", status );
3617 len = 0xdead;
3618 status = pNtSetInformationDebugObject( handle, DebugObjectKillProcessOnExitInformation,
3619 &flag, sizeof(ULONG) + 1, &len );
3620 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationDebugObject failed %lx\n", status );
3621 ok( len == sizeof(ULONG), "wrong len %lu\n", len );
3623 len = 0xdead;
3624 status = pNtSetInformationDebugObject( handle, DebugObjectKillProcessOnExitInformation,
3625 &flag, sizeof(ULONG) - 1, &len );
3626 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationDebugObject failed %lx\n", status );
3627 ok( len == sizeof(ULONG), "wrong len %lu\n", len );
3629 len = 0xdead;
3630 status = pNtSetInformationDebugObject( handle, DebugObjectKillProcessOnExitInformation,
3631 &flag, sizeof(ULONG), &len );
3632 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
3633 ok( !len, "wrong len %lu\n", len );
3635 flag = DEBUG_KILL_ON_CLOSE;
3636 status = pNtSetInformationDebugObject( handle, DebugObjectKillProcessOnExitInformation,
3637 &flag, sizeof(ULONG), &len );
3638 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
3639 ok( !len, "wrong len %lu\n", len );
3641 for (flag = 2; flag; flag <<= 1)
3643 status = pNtSetInformationDebugObject( handle, DebugObjectKillProcessOnExitInformation,
3644 &flag, sizeof(ULONG), &len );
3645 ok( status == STATUS_INVALID_PARAMETER, "NtSetInformationDebugObject failed %lx\n", status );
3648 pNtClose( handle );
3650 memset( &state, 0xdd, sizeof(state) );
3651 state.NewState = DbgIdle;
3652 memset( &event, 0xcc, sizeof(event) );
3653 status = pDbgUiConvertStateChangeStructure( &state, &event );
3654 ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3655 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3656 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3658 state.NewState = DbgReplyPending;
3659 memset( &event, 0xcc, sizeof(event) );
3660 status = pDbgUiConvertStateChangeStructure( &state, &event );
3661 ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3662 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3663 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3665 state.NewState = 11;
3666 memset( &event, 0xcc, sizeof(event) );
3667 status = pDbgUiConvertStateChangeStructure( &state, &event );
3668 ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3669 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3670 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3672 state.NewState = DbgExitProcessStateChange;
3673 state.StateInfo.ExitProcess.ExitStatus = 0x123456;
3674 status = pDbgUiConvertStateChangeStructure( &state, &event );
3675 ok( !status, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3676 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3677 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3678 ok( event.u.ExitProcess.dwExitCode == 0x123456, "event not updated %lx\n", event.u.ExitProcess.dwExitCode );
3680 memset( &state, 0xdd, sizeof(state) );
3681 state.NewState = DbgCreateProcessStateChange;
3682 status = pDbgUiConvertStateChangeStructure( &state, &event );
3683 ok( !status, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3684 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3685 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3686 ok( event.u.CreateProcessInfo.nDebugInfoSize == 0xdddddddd, "event not updated %lx\n", event.u.CreateProcessInfo.nDebugInfoSize );
3687 ok( event.u.CreateProcessInfo.lpThreadLocalBase == NULL, "event not updated %p\n", event.u.CreateProcessInfo.lpThreadLocalBase );
3688 ok( event.u.CreateProcessInfo.lpImageName == NULL, "event not updated %p\n", event.u.CreateProcessInfo.lpImageName );
3689 ok( event.u.CreateProcessInfo.fUnicode == TRUE, "event not updated %x\n", event.u.CreateProcessInfo.fUnicode );
3691 memset( &state, 0xdd, sizeof(state) );
3692 state.NewState = DbgLoadDllStateChange;
3693 status = pDbgUiConvertStateChangeStructure( &state, &event );
3694 ok( !status, "DbgUiConvertStateChangeStructure failed %lx\n", status );
3695 ok( event.dwProcessId == 0xdddddddd, "event not updated %lx\n", event.dwProcessId );
3696 ok( event.dwThreadId == 0xdddddddd, "event not updated %lx\n", event.dwThreadId );
3697 ok( event.u.LoadDll.nDebugInfoSize == 0xdddddddd, "event not updated %lx\n", event.u.LoadDll.nDebugInfoSize );
3698 ok( PtrToUlong(event.u.LoadDll.lpImageName) == 0xdddddddd, "event not updated %p\n", event.u.LoadDll.lpImageName );
3699 ok( event.u.LoadDll.fUnicode == TRUE, "event not updated %x\n", event.u.LoadDll.fUnicode );
3702 static void test_process_instrumentation_callback(void)
3704 PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION info;
3705 NTSTATUS status;
3707 status = NtSetInformationProcess( GetCurrentProcess(), ProcessInstrumentationCallback, NULL, 0 );
3708 ok( status == STATUS_INFO_LENGTH_MISMATCH /* Win10 */ || status == STATUS_INVALID_INFO_CLASS
3709 || status == STATUS_NOT_SUPPORTED, "Got unexpected status %#lx.\n", status );
3710 if (status != STATUS_INFO_LENGTH_MISMATCH)
3712 win_skip( "ProcessInstrumentationCallback is not supported.\n" );
3713 return;
3716 memset(&info, 0, sizeof(info));
3717 status = NtSetInformationProcess( GetCurrentProcess(), ProcessInstrumentationCallback, &info, sizeof(info) );
3718 ok( status == STATUS_SUCCESS /* Win 10 */ || broken( status == STATUS_PRIVILEGE_NOT_HELD )
3719 || broken( status == STATUS_INFO_LENGTH_MISMATCH ), "Got unexpected status %#lx.\n", status );
3721 memset(&info, 0, sizeof(info));
3722 status = NtSetInformationProcess( GetCurrentProcess(), ProcessInstrumentationCallback, &info, 2 * sizeof(info) );
3723 ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH
3724 || broken( status == STATUS_PRIVILEGE_NOT_HELD ) /* some versions and machines before Win10 */,
3725 "Got unexpected status %#lx.\n", status );
3728 static void test_debuggee_dbgport(int argc, char **argv)
3730 NTSTATUS status, expect_status;
3731 DWORD_PTR debug_port = 0xdeadbeef;
3732 DWORD debug_flags = 0xdeadbeef;
3733 HANDLE handle;
3734 ACCESS_MASK access;
3736 if (argc < 2)
3738 ok(0, "insufficient arguments for child process\n");
3739 return;
3742 access = strtoul(argv[1], NULL, 0);
3743 winetest_push_context("debug object access %08lx", access);
3745 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessDebugPort,
3746 &debug_port, sizeof(debug_port), NULL );
3747 ok( !status, "NtQueryInformationProcess ProcessDebugPort failed, status %#lx.\n", status );
3748 ok( debug_port == ~(DWORD_PTR)0, "Expected port %#Ix, got %#Ix.\n", ~(DWORD_PTR)0, debug_port );
3750 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessDebugFlags,
3751 &debug_flags, sizeof(debug_flags), NULL );
3752 ok( !status, "NtQueryInformationProcess ProcessDebugFlags failed, status %#lx.\n", status );
3754 expect_status = access ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
3755 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessDebugObjectHandle,
3756 &handle, sizeof(handle), NULL );
3757 ok( status == expect_status, "NtQueryInformationProcess ProcessDebugObjectHandle expected status %#lx, actual %#lx.\n", expect_status, status );
3758 if (SUCCEEDED( status )) NtClose( handle );
3760 winetest_pop_context();
3763 static DWORD WINAPI test_ThreadIsTerminated_thread( void *stop_event )
3765 WaitForSingleObject( stop_event, INFINITE );
3766 return STATUS_PENDING;
3769 static void test_ThreadIsTerminated(void)
3771 HANDLE thread, stop_event;
3772 ULONG terminated;
3773 NTSTATUS status;
3775 stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
3776 thread = CreateThread( NULL, 0, test_ThreadIsTerminated_thread, stop_event, 0, NULL );
3777 ok( thread != INVALID_HANDLE_VALUE, "failed, error %ld\n", GetLastError() );
3779 status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated) * 2, NULL );
3780 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx.\n", status );
3782 terminated = 0xdeadbeef;
3783 status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
3784 ok( !status, "got %#lx.\n", status );
3785 ok( !terminated, "got %lu.\n", terminated );
3787 SetEvent( stop_event );
3788 WaitForSingleObject( thread, INFINITE );
3790 status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
3791 ok( !status, "got %#lx.\n", status );
3792 ok( terminated == 1, "got %lu.\n", terminated );
3794 CloseHandle(stop_event);
3795 CloseHandle(thread);
3797 status = pNtQueryInformationThread( thread, ThreadIsTerminated, &terminated, sizeof(terminated), NULL );
3798 ok( status == STATUS_INVALID_HANDLE, "got %#lx.\n", status );
3801 static void test_system_debug_control(void)
3803 NTSTATUS status;
3804 int class;
3806 for (class = 0; class < SysDbgMaxInfoClass; ++class)
3808 status = pNtSystemDebugControl( class, NULL, 0, NULL, 0, NULL );
3809 if (is_wow64)
3811 /* Most of the calls return STATUS_NOT_IMPLEMENTED on wow64. */
3812 ok( status == STATUS_DEBUGGER_INACTIVE || status == STATUS_NOT_IMPLEMENTED || status == STATUS_INFO_LENGTH_MISMATCH,
3813 "class %d, got %#lx.\n", class, status );
3815 else
3817 ok( status == STATUS_DEBUGGER_INACTIVE || status == STATUS_ACCESS_DENIED || status == STATUS_INFO_LENGTH_MISMATCH,
3818 "class %d, got %#lx.\n", class, status );
3823 static void test_process_token(int argc, char **argv)
3825 STARTUPINFOA si = {.cb = sizeof(si)};
3826 PROCESS_ACCESS_TOKEN token_info = {0};
3827 TOKEN_STATISTICS stats1, stats2;
3828 HANDLE token, their_token;
3829 PROCESS_INFORMATION pi;
3830 char cmdline[MAX_PATH];
3831 NTSTATUS status;
3832 DWORD size;
3833 BOOL ret;
3835 token_info.Thread = (HANDLE)0xdeadbeef;
3837 sprintf( cmdline, "%s %s dummy", argv[0], argv[1] );
3839 ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi );
3840 ok( ret, "got error %lu\n", GetLastError() );
3842 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) - 1 );
3843 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status );
3845 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
3846 ok( status == STATUS_INVALID_HANDLE, "got %#lx\n", status );
3848 ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | READ_CONTROL | TOKEN_DUPLICATE
3849 | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &token );
3850 ok( ret, "got error %lu\n", GetLastError() );
3852 token_info.Token = token;
3853 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
3854 todo_wine ok( status == STATUS_TOKEN_ALREADY_IN_USE, "got %#lx\n", status );
3856 ret = DuplicateTokenEx( token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenImpersonation, &token_info.Token );
3857 ok( ret, "got error %lu\n", GetLastError() );
3858 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
3859 todo_wine ok( status == STATUS_BAD_IMPERSONATION_LEVEL, "got %#lx\n", status );
3860 CloseHandle( token_info.Token );
3862 ret = DuplicateTokenEx( token, TOKEN_QUERY, NULL, SecurityAnonymous, TokenPrimary, &token_info.Token );
3863 ok( ret, "got error %lu\n", GetLastError() );
3864 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
3865 ok( status == STATUS_ACCESS_DENIED, "got %#lx\n", status );
3866 CloseHandle( token_info.Token );
3868 ret = DuplicateTokenEx( token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, NULL, SecurityAnonymous, TokenPrimary, &token_info.Token );
3869 ok(ret, "got error %lu\n", GetLastError());
3870 status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
3871 ok( status == STATUS_SUCCESS, "got %#lx\n", status );
3873 ret = OpenProcessToken( pi.hProcess, TOKEN_QUERY, &their_token );
3874 ok( ret, "got error %lu\n", GetLastError() );
3876 /* The tokens should be the same. */
3877 ret = GetTokenInformation( token_info.Token, TokenStatistics, &stats1, sizeof(stats1), &size );
3878 ok( ret, "got error %lu\n", GetLastError() );
3879 ret = GetTokenInformation( their_token, TokenStatistics, &stats2, sizeof(stats2), &size );
3880 ok( ret, "got error %lu\n", GetLastError() );
3881 ok( !memcmp( &stats1.TokenId, &stats2.TokenId, sizeof(LUID) ), "expected same IDs\n" );
3883 CloseHandle( token_info.Token );
3884 CloseHandle( their_token );
3886 ResumeThread( pi.hThread );
3887 ret = WaitForSingleObject( pi.hProcess, 1000 );
3888 ok( !ret, "got %d\n", ret );
3890 CloseHandle( pi.hProcess );
3891 CloseHandle( pi.hThread );
3892 CloseHandle( token );
3895 static void test_process_id(void)
3897 char image_name_buffer[1024 * sizeof(WCHAR)];
3898 UNICODE_STRING *image_name = (UNICODE_STRING *)image_name_buffer;
3899 SYSTEM_PROCESS_ID_INFORMATION info;
3900 unsigned int i, length;
3901 DWORD pids[2048];
3902 WCHAR name[2048];
3903 NTSTATUS status;
3904 HANDLE process;
3905 ULONG len;
3906 BOOL bret;
3908 status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, image_name,
3909 sizeof(image_name_buffer), NULL );
3910 ok( !status, "got %#lx.\n", status );
3911 length = image_name->Length;
3912 image_name->Buffer[length] = 0;
3914 len = 0xdeadbeef;
3915 status = pNtQuerySystemInformation( SystemProcessIdInformation, NULL, 0, &len );
3916 ok( status == STATUS_INFO_LENGTH_MISMATCH || (is_wow64 && status == STATUS_ACCESS_VIOLATION), "got %#lx.\n", status );
3917 ok( len == sizeof(info) || (is_wow64 && len == 0xdeadbeef), "got %#lx.\n", len );
3919 info.ProcessId = 0xdeadbeef;
3920 info.ImageName.Length = info.ImageName.MaximumLength = 0;
3921 info.ImageName.Buffer = NULL;
3922 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3923 ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
3924 ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
3925 ok( !info.ImageName.MaximumLength, "got %#x.\n", info.ImageName.MaximumLength );
3927 info.ProcessId = GetCurrentProcessId();
3928 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3929 ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx.\n", status );
3930 ok( len == sizeof(info), "got %#lx.\n", len );
3931 ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
3932 ok( info.ImageName.MaximumLength == length + 2 || (is_wow64 && !info.ImageName.MaximumLength),
3933 "got %#x.\n", info.ImageName.MaximumLength );
3935 info.ImageName.MaximumLength = sizeof(name);
3936 len = 0xdeadbeef;
3937 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3938 ok( status == STATUS_ACCESS_VIOLATION, "got %#lx.\n", status );
3939 ok( len == sizeof(info), "got %#lx.\n", len );
3940 ok( info.ImageName.Length == length || (is_wow64 && !info.ImageName.Length),
3941 "got %u.\n", info.ImageName.Length );
3942 ok( info.ImageName.MaximumLength == length + 2 || (is_wow64 && !info.ImageName.Length),
3943 "got %#x.\n", info.ImageName.MaximumLength );
3945 info.ProcessId = 0xdeadbeef;
3946 info.ImageName.MaximumLength = sizeof(name);
3947 info.ImageName.Buffer = name;
3948 info.ImageName.Length = 0;
3949 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3950 ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
3951 ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
3952 ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n", info.ImageName.MaximumLength );
3953 ok( info.ImageName.Buffer == name, "got %p, %p.\n", info.ImageName.Buffer, name );
3955 info.ProcessId = 0;
3956 info.ImageName.MaximumLength = sizeof(name);
3957 info.ImageName.Buffer = name;
3958 info.ImageName.Length = 0;
3959 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3960 ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
3961 ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
3962 ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n", info.ImageName.MaximumLength );
3963 ok( info.ImageName.Buffer == name, "got non NULL.\n" );
3965 info.ProcessId = 0;
3966 info.ImageName.MaximumLength = sizeof(name);
3967 info.ImageName.Buffer = name;
3968 info.ImageName.Length = 4;
3969 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3970 ok( status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status );
3971 ok( info.ImageName.Length == 4, "got %#x.\n", info.ImageName.Length );
3972 ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n", info.ImageName.MaximumLength );
3973 ok( info.ImageName.Buffer == name, "got non NULL.\n" );
3975 info.ProcessId = GetCurrentProcessId();
3976 info.ImageName.MaximumLength = sizeof(name);
3977 info.ImageName.Buffer = name;
3978 info.ImageName.Length = 4;
3979 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), NULL );
3980 ok( status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status );
3981 ok( info.ImageName.Length == 4, "got %#x.\n", info.ImageName.Length );
3982 ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n", info.ImageName.MaximumLength );
3984 info.ImageName.Length = 0;
3985 memset( name, 0xcc, sizeof(name) );
3986 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
3987 ok( !status, "got %#lx.\n", status );
3988 ok( info.ImageName.Length == length, "got %#x.\n", info.ImageName.Length );
3989 ok( len == sizeof(info), "got %#lx.\n", len );
3990 ok( info.ImageName.MaximumLength == info.ImageName.Length + 2, "got %#x.\n", info.ImageName.MaximumLength );
3991 ok( !name[info.ImageName.Length / 2], "got %#x.\n", name[info.ImageName.Length / 2] );
3993 ok( info.ImageName.Length == image_name->Length, "got %#x, %#x.\n", info.ImageName.Length, image_name->Length );
3994 ok( !wcscmp( name, image_name->Buffer ), "got %s, %s.\n", debugstr_w(name), debugstr_w(image_name->Buffer) );
3996 bret = EnumProcesses( pids, sizeof(pids), &len );
3997 ok( bret, "got error %lu.\n", GetLastError() );
3998 for (i = 0; i < len / sizeof(*pids); ++i)
4000 process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pids[i] );
4001 if (pids[i] && !process && GetLastError() != ERROR_ACCESS_DENIED)
4003 /* process is gone already. */
4004 continue;
4006 info.ProcessId = pids[i];
4007 info.ImageName.Length = 0;
4008 info.ImageName.MaximumLength = sizeof(name);
4009 info.ImageName.Buffer = name;
4010 status = pNtQuerySystemInformation( SystemProcessIdInformation, &info, sizeof(info), &len );
4011 ok( info.ImageName.Buffer == name || (!info.ImageName.MaximumLength && !info.ImageName.Length),
4012 "got %p, %p, pid %lu, lengh %u / %u.\n", info.ImageName.Buffer, name, pids[i],
4013 info.ImageName.Length, info.ImageName.MaximumLength );
4014 if (pids[i])
4015 ok( !status, "got %#lx, pid %lu.\n", status, pids[i] );
4016 else
4017 ok( status == STATUS_INVALID_CID, "got %#lx, pid %lu.\n", status, pids[i] );
4018 if (process) CloseHandle( process );
4022 START_TEST(info)
4024 char **argv;
4025 int argc;
4027 InitFunctionPtrs();
4029 argc = winetest_get_mainargs(&argv);
4030 if (argc >= 3)
4032 if (strcmp(argv[2], "debuggee:dbgport") == 0) test_debuggee_dbgport(argc - 2, argv + 2);
4033 return; /* Child */
4036 /* NtQuerySystemInformation */
4037 test_query_basic();
4038 test_query_cpu();
4039 test_query_performance();
4040 test_query_timeofday();
4041 test_query_process( TRUE );
4042 test_query_process( FALSE );
4043 test_query_procperf();
4044 test_query_module();
4045 test_query_handle();
4046 test_query_handle_ex();
4047 test_query_cache();
4048 test_query_interrupt();
4049 test_time_adjustment();
4050 test_query_kerndebug();
4051 test_query_regquota();
4052 test_query_logicalproc();
4053 test_query_logicalprocex();
4054 test_query_cpusetinfo();
4055 test_query_firmware();
4056 test_query_data_alignment();
4058 /* NtPowerInformation */
4059 test_query_battery();
4060 test_query_processor_power_info();
4062 /* NtQueryInformationProcess */
4063 test_query_process_basic();
4064 test_query_process_io();
4065 test_query_process_vm();
4066 test_query_process_times();
4067 test_query_process_debug_port(argc, argv);
4068 test_query_process_debug_port_custom_dacl(argc, argv);
4069 test_query_process_priority();
4070 test_query_process_handlecount();
4071 test_query_process_wow64();
4072 test_query_process_image_file_name();
4073 test_query_process_debug_object_handle(argc, argv);
4074 test_query_process_debug_flags(argc, argv);
4075 test_query_process_image_info();
4076 test_query_process_quota_limits();
4077 test_mapprotection();
4078 test_threadstack();
4080 /* NtQueryInformationThread */
4081 test_thread_info();
4082 test_HideFromDebugger();
4083 test_thread_start_address();
4084 test_thread_lookup();
4085 test_thread_ideal_processor();
4086 test_ThreadIsTerminated();
4088 test_affinity();
4089 test_debug_object();
4091 /* belongs to its own file */
4092 test_readvirtualmemory();
4093 test_queryvirtualmemory();
4094 test_NtGetCurrentProcessorNumber();
4096 test_ThreadEnableAlignmentFaultFixup();
4097 test_process_instrumentation_callback();
4098 test_system_debug_control();
4099 test_process_token(argc, argv);
4100 test_process_id();