Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - don't introduce different behaviour based on is_win64.
dlls/ntdll/tests/info.c | 90 ++++++++++++++++++++++++++++- dlls/ntdll/unix/system.c | 120 +++++++++++++++++++++++++++++++++++++++ include/winnt.h | 41 +++++++++++++ include/winternl.h | 1 + 4 files changed, 251 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 85c523881ef..f3e4ebdf8bb 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -21,6 +21,7 @@ #include "ntdll_test.h" #include <winnls.h> #include <stdio.h> +#include "wine/heap.h"
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG); @@ -46,8 +47,8 @@ static NTSTATUS (WINAPI * pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void static NTSTATUS (WINAPI * pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG ); static NTSTATUS (WINAPI * pNtSetInformationDebugObject)(HANDLE,DEBUGOBJECTINFOCLASS,PVOID,ULONG,ULONG*); static NTSTATUS (WINAPI * pDbgUiConvertStateChangeStructure)(DBGUI_WAIT_STATE_CHANGE*,DEBUG_EVENT*); - static BOOL is_wow64; +static const BOOL is_win64 = sizeof(void *) > sizeof(int);
/* one_before_last_pid is used to be able to compare values of a still running process with the output of the test_query_process_times and test_query_process_handlecount tests. @@ -1099,6 +1100,92 @@ static void test_query_logicalprocex(void) HeapFree(GetProcessHeap(), 0, infoex_group); }
+static void test_query_cpusetinfo(void) +{ + SYSTEM_CPU_SET_INFORMATION *info; + unsigned int i, cpu_count; + ULONG len, expected_len; + NTSTATUS status; + SYSTEM_INFO si; + HANDLE process; + + if (!pNtQuerySystemInformationEx) + return; + + GetSystemInfo(&si); + cpu_count = si.dwNumberOfProcessors; + expected_len = cpu_count * sizeof(*info); + + process = GetCurrentProcess(); + + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len); + if (status == STATUS_INVALID_INFO_CLASS) + { + win_skip("SystemCpuSetInformation is not supported\n"); + return; + } + + ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status); + ok(len == expected_len, "Got unexpected length %u.\n", len); + + len = 0xdeadbeef; + status = pNtQuerySystemInformation(SystemCpuSetInformation, NULL, 0, &len); + todo_wine_if(!is_win64 && status == STATUS_INVALID_PARAMETER) + ok(status == (is_win64 ? STATUS_INVALID_PARAMETER : STATUS_INVALID_INFO_CLASS), + "Got unexpected status %#x.\n", status); + ok(len == 0xdeadbeef, "Got unexpected len %u.\n", len); + + len = 0xdeadbeef; + process = (HANDLE)0xdeadbeef; + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len); + ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#x.\n", status); + ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len); + + len = 0xdeadbeef; + process = NULL; + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, 4 * sizeof(process), NULL, 0, &len); + todo_wine_if(is_win64 && status == STATUS_BUFFER_TOO_SMALL) + ok(status == (is_win64 ? STATUS_INVALID_PARAMETER : STATUS_BUFFER_TOO_SMALL), + "Got unexpected status %#x.\n", status); + todo_wine_if(is_win64 && len == expected_len) + ok(len == (is_win64 ? 0xdeadbeef : expected_len), "Got unexpected length %u.\n", len); + + len = 0xdeadbeef; + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, NULL, sizeof(process), NULL, 0, &len); + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len); + + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len); + ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status); + ok(len == expected_len, "Got unexpected length %u.\n", len); + + len = 0xdeadbeef; + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, + expected_len, &len); + ok(status == STATUS_ACCESS_VIOLATION, "Got unexpected status %#x.\n", status); + ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len); + + info = heap_alloc(expected_len); + len = 0; + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), info, expected_len, &len); + ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status); + ok(len == expected_len, "Got unexpected length %u.\n", len); + + for (i = 0; i < cpu_count; ++i) + { + SYSTEM_CPU_SET_INFORMATION *d = &info[i]; + + ok(d->Size == sizeof(*d), "Got unexpected size %u, i %u.\n", d->Size, i); + ok(d->Type == CpuSetInformation, "Got unexpected type %u, i %u.\n", d->Type, i); + ok(d->CpuSet.Id == 0x100 + i, "Got unexpected Id %#x, i %u.\n", d->CpuSet.Id, i); + ok(!d->CpuSet.Group, "Got unexpected Group %u, i %u.\n", d->CpuSet.Group, i); + ok(d->CpuSet.LogicalProcessorIndex == i, "Got unexpected LogicalProcessorIndex %u, i %u.\n", + d->CpuSet.LogicalProcessorIndex, i); + ok(!d->CpuSet.AllFlags, "Got unexpected AllFlags %#x, i %u.\n", d->CpuSet.AllFlags, i); + } + heap_free(info); +} + static void test_query_firmware(void) { static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); @@ -3059,6 +3146,7 @@ START_TEST(info) test_query_regquota(); test_query_logicalproc(); test_query_logicalprocex(); + test_query_cpusetinfo(); test_query_firmware(); test_query_data_alignment();
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 6fa71ddfb91..a9cd686ed62 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -1166,6 +1166,98 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION * } #endif
+static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info) +{ + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *proc_info; + BYTE core_index, cache_index, max_cache_level; + unsigned int i, j, count; + BYTE *proc_info_buffer; + DWORD cpu_info_size; + ULONG64 cpu_mask; + NTSTATUS status; + + count = NtCurrentTeb()->Peb->NumberOfProcessors; + + cpu_info_size = 3 * sizeof(*proc_info); + if (!(proc_info_buffer = malloc(cpu_info_size))) + return STATUS_NO_MEMORY; + + if ((status = create_logical_proc_info(NULL, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **)&proc_info_buffer, + &cpu_info_size, RelationAll))) + { + free(proc_info_buffer); + return status; + } + + max_cache_level = 0; + proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)proc_info_buffer; + for (i = 0; (BYTE *)proc_info != proc_info_buffer + cpu_info_size; ++i) + { + if (proc_info->Relationship == RelationCache) + { + if (max_cache_level < proc_info->u.Cache.Level) + max_cache_level = proc_info->u.Cache.Level; + } + proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((BYTE *)proc_info + proc_info->Size); + } + + memset(info, 0, count * sizeof(*info)); + + core_index = 0; + cache_index = 0; + proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)proc_info_buffer; + for (i = 0; i < count; ++i) + { + info[i].Size = sizeof(*info); + info[i].Type = CpuSetInformation; + info[i].u.CpuSet.Id = 0x100 + i; + info[i].u.CpuSet.LogicalProcessorIndex = i; + } + + for (i = 0; (BYTE *)proc_info != (BYTE *)proc_info_buffer + cpu_info_size; ++i) + { + if (proc_info->Relationship == RelationProcessorCore) + { + if (proc_info->u.Processor.GroupCount != 1) + { + FIXME("Unsupported group count %u.\n", proc_info->u.Processor.GroupCount); + continue; + } + cpu_mask = proc_info->u.Processor.GroupMask[0].Mask; + for (j = 0; j < count; ++j) + if (((ULONG64)1 << j) & cpu_mask) + { + info[j].u.CpuSet.CoreIndex = core_index; + info[j].u.CpuSet.EfficiencyClass = proc_info->u.Processor.EfficiencyClass; + } + ++core_index; + } + else if (proc_info->Relationship == RelationCache) + { + if (proc_info->u.Cache.Level == max_cache_level) + { + cpu_mask = proc_info->u.Cache.GroupMask.Mask; + for (j = 0; j < count; ++j) + if (((ULONG64)1 << j) & cpu_mask) + info[j].u.CpuSet.LastLevelCacheIndex = cache_index; + } + ++cache_index; + } + else if (proc_info->Relationship == RelationNumaNode) + { + cpu_mask = proc_info->u.NumaNode.GroupMask.Mask; + for (j = 0; j < count; ++j) + if (((ULONG64)1 << j) & cpu_mask) + info[j].u.CpuSet.NumaNodeIndex = proc_info->u.NumaNode.NodeNumber; + } + proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((BYTE *)proc_info + proc_info->Size); + } + + free(proc_info_buffer); + + return STATUS_SUCCESS; +} + #ifdef linux
static void copy_smbios_string( char **buffer, char *s, size_t len ) @@ -2651,6 +2743,9 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, break; }
+ case SystemCpuSetInformation: + return NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size); + case SystemRecommendedSharedDataAlignment: { len = sizeof(DWORD); @@ -2773,6 +2868,31 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class, break; }
+ case SystemCpuSetInformation: + { + unsigned int cpu_count = NtCurrentTeb()->Peb->NumberOfProcessors; + PROCESS_BASIC_INFORMATION pbi; + HANDLE process; + + if (!query || query_len < sizeof(HANDLE)) + return STATUS_INVALID_PARAMETER; + + process = *(HANDLE *)query; + if (process && (ret = NtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL))) + return ret; + + if (size < (len = cpu_count * sizeof(SYSTEM_CPU_SET_INFORMATION))) + { + ret = STATUS_BUFFER_TOO_SMALL; + break; + } + if (!info) + return STATUS_ACCESS_VIOLATION; + + if ((ret = create_cpuset_info(info))) + return ret; + break; + } default: FIXME( "(0x%08x,%p,%u,%p,%u,%p) stub\n", class, query, query_len, info, size, ret_size ); break; diff --git a/include/winnt.h b/include/winnt.h index 0a6027118fe..840966f657b 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -6726,6 +6726,47 @@ typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX } DUMMYUNIONNAME; } SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
+typedef enum _CPU_SET_INFORMATION_TYPE +{ + CpuSetInformation, +} CPU_SET_INFORMATION_TYPE, *PCPU_SET_INFORMATION_TYPE; + +typedef struct _SYSTEM_CPU_SET_INFORMATION +{ + DWORD Size; + CPU_SET_INFORMATION_TYPE Type; + union + { + struct + { + DWORD Id; + WORD Group; + BYTE LogicalProcessorIndex; + BYTE CoreIndex; + BYTE LastLevelCacheIndex; + BYTE NumaNodeIndex; + BYTE EfficiencyClass; + union + { + BYTE AllFlags; + struct + { + BYTE Parked : 1; + BYTE Allocated : 1; + BYTE AllocatedToTargetProcess : 1; + BYTE RealTime : 1; + BYTE ReservedFlags : 4; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME2; + union { + DWORD Reserved; + BYTE SchedulingClass; + }; + DWORD64 AllocationTag; + } CpuSet; + } DUMMYUNIONNAME; +} SYSTEM_CPU_SET_INFORMATION, *PSYSTEM_CPU_SET_INFORMATION; + /* Threadpool things */ typedef DWORD TP_VERSION,*PTP_VERSION;
diff --git a/include/winternl.h b/include/winternl.h index fcdedaec8aa..c8fb7031d91 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1551,6 +1551,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS { SystemFileCacheInformationEx = 81, SystemDynamicTimeZoneInformation = 102, SystemLogicalProcessorInformationEx = 107, + SystemCpuSetInformation = 175, SystemHypervisorSharedPageInformation = 197, SystemInformationClassMax } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- ...api-ms-win-core-processthreads-l1-1-3.spec | 2 +- dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/tests/process.c | 66 +++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/memory.c | 16 +++++ include/winbase.h | 1 + 6 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/dlls/api-ms-win-core-processthreads-l1-1-3/api-ms-win-core-processthreads-l1-1-3.spec b/dlls/api-ms-win-core-processthreads-l1-1-3/api-ms-win-core-processthreads-l1-1-3.spec index 9cc853d2884..8f2daaefe74 100644 --- a/dlls/api-ms-win-core-processthreads-l1-1-3/api-ms-win-core-processthreads-l1-1-3.spec +++ b/dlls/api-ms-win-core-processthreads-l1-1-3/api-ms-win-core-processthreads-l1-1-3.spec @@ -1,6 +1,6 @@ @ stub GetProcessDefaultCpuSets @ stub GetProcessInformation -@ stub GetSystemCpuSetInformation +@ stdcall GetSystemCpuSetInformation(ptr long ptr ptr long) kernel32.GetSystemCpuSetInformation @ stdcall GetThreadDescription(long ptr) kernel32.GetThreadDescription @ stub GetThreadSelectedCpuSets @ stub SetProcessDefaultCpuSets diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index d14bf010383..0312e044a86 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -822,6 +822,7 @@ @ stdcall GetStringTypeExA(long long str long ptr) @ stdcall -import GetStringTypeExW(long long wstr long ptr) @ stdcall -import GetStringTypeW(long wstr long ptr) +@ stdcall -import GetSystemCpuSetInformation(ptr long ptr ptr long) @ stdcall -import GetSystemFileCacheSize(ptr ptr ptr) @ stdcall -import GetSystemDefaultLCID() @ stdcall -import GetSystemDefaultLangID() diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 373212cd2da..433c12ff1fb 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -79,6 +79,7 @@ static BOOL (WINAPI *pSetInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS static HANDLE (WINAPI *pCreateIoCompletionPort)(HANDLE file, HANDLE existing_port, ULONG_PTR key, DWORD threads); static BOOL (WINAPI *pGetNumaProcessorNode)(UCHAR, PUCHAR); static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); +static NTSTATUS (WINAPI *pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*); static DWORD (WINAPI *pWTSGetActiveConsoleSessionId)(void); static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD); static BOOL (WINAPI *pProcess32First)(HANDLE, PROCESSENTRY32*); @@ -87,6 +88,7 @@ static BOOL (WINAPI *pThread32First)(HANDLE, THREADENTRY32*); static BOOL (WINAPI *pThread32Next)(HANDLE, THREADENTRY32*); static BOOL (WINAPI *pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*); static SIZE_T (WINAPI *pGetLargePageMinimum)(void); +static BOOL (WINAPI *pGetSystemCpuSetInformation)(SYSTEM_CPU_SET_INFORMATION*,ULONG,ULONG*,HANDLE,ULONG); static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*); static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*); static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*); @@ -245,6 +247,7 @@ static BOOL init(void) hntdll = GetModuleHandleA("ntdll.dll");
pNtQueryInformationProcess = (void *)GetProcAddress(hntdll, "NtQueryInformationProcess"); + pNtQuerySystemInformationEx = (void *)GetProcAddress(hntdll, "NtQuerySystemInformationEx");
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo"); pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota"); @@ -269,6 +272,7 @@ static BOOL init(void) pThread32Next = (void *)GetProcAddress(hkernel32, "Thread32Next"); pGetLogicalProcessorInformationEx = (void *)GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx"); pGetLargePageMinimum = (void *)GetProcAddress(hkernel32, "GetLargePageMinimum"); + pGetSystemCpuSetInformation = (void *)GetProcAddress(hkernel32, "GetSystemCpuSetInformation"); pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList"); pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute"); pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList"); @@ -3786,6 +3790,67 @@ static void test_GetLogicalProcessorInformationEx(void) HeapFree(GetProcessHeap(), 0, info); }
+static void test_GetSystemCpuSetInformation(void) +{ + SYSTEM_CPU_SET_INFORMATION *info, *info_nt; + HANDLE process = GetCurrentProcess(); + ULONG size, expected_size; + NTSTATUS status; + SYSTEM_INFO si; + BOOL ret; + + if (!pGetSystemCpuSetInformation) + { + win_skip("GetSystemCpuSetInformation() is not supported.\n"); + return; + } + + GetSystemInfo(&si); + + expected_size = sizeof(*info) * si.dwNumberOfProcessors; + + if (0) + { + /* Crashes on Windows with NULL return length. */ + pGetSystemCpuSetInformation(NULL, 0, NULL, process, 0); + } + + size = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = pGetSystemCpuSetInformation(NULL, size, &size, process, 0); + ok(!ret && GetLastError() == ERROR_NOACCESS, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ok(!size, "Got unexpected size %u.\n", size); + + size = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = pGetSystemCpuSetInformation(NULL, 0, &size, (HANDLE)0xdeadbeef, 0); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ok(!size, "Got unexpected size %u.\n", size); + + size = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = pGetSystemCpuSetInformation(NULL, 0, &size, process, 0); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ok(size == expected_size, "Got unexpected size %u.\n", size); + + info = heap_alloc(size); + info_nt = heap_alloc(size); + + status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), info_nt, expected_size, NULL); + ok(!status, "Got unexpected status %#x.\n", status); + + size = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = pGetSystemCpuSetInformation(info, expected_size, &size, process, 0); + ok(ret && GetLastError() == 0xdeadbeef, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ok(size == expected_size, "Got unexpected size %u.\n", size); + + ok(!memcmp(info, info_nt, expected_size), "Info does not match NtQuerySystemInformationEx()."); + + heap_free(info_nt); + heap_free(info); +} + static void test_largepages(void) { SIZE_T size; @@ -4348,6 +4413,7 @@ START_TEST(process) test_GetNumaProcessorNode(); test_session_info(); test_GetLogicalProcessorInformationEx(); + test_GetSystemCpuSetInformation(); test_largepages(); test_ProcThreadAttributeList(); test_SuspendProcessState(); diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 08a2f726817..8cb15fff084 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -681,7 +681,7 @@ @ stdcall GetStringTypeW(long wstr long ptr) # @ stub GetSystemAppDataFolder # @ stub GetSystemAppDataKey -# @ stub GetSystemCpuSetInformation +@ stdcall GetSystemCpuSetInformation(ptr long ptr ptr long) @ stdcall GetSystemDefaultLCID() @ stdcall GetSystemDefaultLangID() @ stdcall GetSystemDefaultLocaleName(ptr long) diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 2bfd3893e8e..60333db242f 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -1130,6 +1130,22 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformationEx( LOGICAL_PROCESSO }
+/*********************************************************************** + * GetSystemCpuSetInformation (kernelbase.@) + */ +BOOL WINAPI GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION *info, ULONG buffer_length, ULONG *return_length, + HANDLE process, ULONG flags) +{ + if (flags) + FIXME("Unsupported flags %#x.\n", flags); + + *return_length = 0; + + return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation, &process, sizeof(process), info, + buffer_length, return_length )); +} + + /********************************************************************** * GetNumaHighestNodeNumber (kernelbase.@) */ diff --git a/include/winbase.h b/include/winbase.h index 651da6d6906..beb91371bb6 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2274,6 +2274,7 @@ WINBASEAPI VOID WINAPI GetStartupInfoA(LPSTARTUPINFOA); WINBASEAPI VOID WINAPI GetStartupInfoW(LPSTARTUPINFOW); #define GetStartupInfo WINELIB_NAME_AW(GetStartupInfo) WINBASEAPI HANDLE WINAPI GetStdHandle(DWORD); +WINBASEAPI BOOL WINAPI GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION*,ULONG,ULONG*,HANDLE,ULONG); WINBASEAPI UINT WINAPI GetSystemDirectoryA(LPSTR,UINT); WINBASEAPI UINT WINAPI GetSystemDirectoryW(LPWSTR,UINT); #define GetSystemDirectory WINELIB_NAME_AW(GetSystemDirectory)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=87893
Your paranoid android.
=== build (build log) ===
WineRunBuild.pl:error: The build timed out
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=87892
Your paranoid android.
=== build (build log) ===
WineRunBuild.pl:error: The build timed out
Paul Gofman pgofman@codeweavers.com writes:
+static void test_query_cpusetinfo(void) +{
- SYSTEM_CPU_SET_INFORMATION *info;
- unsigned int i, cpu_count;
- ULONG len, expected_len;
- NTSTATUS status;
- SYSTEM_INFO si;
- HANDLE process;
- if (!pNtQuerySystemInformationEx)
return;
- GetSystemInfo(&si);
- cpu_count = si.dwNumberOfProcessors;
- expected_len = cpu_count * sizeof(*info);
- process = GetCurrentProcess();
- status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
- if (status == STATUS_INVALID_INFO_CLASS)
- {
win_skip("SystemCpuSetInformation is not supported\n");
return;
- }
- ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status);
- ok(len == expected_len, "Got unexpected length %u.\n", len);
- len = 0xdeadbeef;
- status = pNtQuerySystemInformation(SystemCpuSetInformation, NULL, 0, &len);
- todo_wine_if(!is_win64 && status == STATUS_INVALID_PARAMETER)
- ok(status == (is_win64 ? STATUS_INVALID_PARAMETER : STATUS_INVALID_INFO_CLASS),
"Got unexpected status %#x.\n", status);
- ok(len == 0xdeadbeef, "Got unexpected len %u.\n", len);
You should avoid is_win64 checks in the tests as well. Simply allow both values, or allow just one and mark the other broken.