Signed-off-by: Paul Gofman pgofman@codeweavers.com --- resend: - rebased the patch.
dlls/ntdll/tests/info.c | 87 +++++++++++++++++++++++++++- dlls/ntdll/unix/system.c | 121 +++++++++++++++++++++++++++++++++++++++ include/winnt.h | 41 +++++++++++++ include/winternl.h | 1 + 4 files changed, 249 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 85c523881ef..80ad333031c 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,89 @@ 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); + 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); + ok(status == (is_win64 ? STATUS_INVALID_PARAMETER : STATUS_BUFFER_TOO_SMALL), + "Got unexpected status %#x.\n", status); + 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 +3143,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..859193944aa 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,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, break; }
+ case SystemCpuSetInformation: + return is_win64 ? NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size) + : STATUS_INVALID_INFO_CLASS; + case SystemRecommendedSharedDataAlignment: { len = sizeof(DWORD); @@ -2773,6 +2869,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) || (is_win64 && 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=87867
Your paranoid android.
=== w1064 (32 bit report) ===
kernel32: process.c:4108: Test failed: Got unexpected ret 0x1, GetLastError() 1813. process.c:4122: Test failed: Got unexpected ret 0x1, GetLastError() 1813. process.c:4051: Test failed: Got unexpected ret 0, level 2, GetLastError() 6. process.c:4058: Test failed: Got parent id 7176, parent_data.parent_id 0.
Paul Gofman pgofman@codeweavers.com writes:
@@ -2651,6 +2743,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, break; }
- case SystemCpuSetInformation:
return is_win64 ? NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size)
: STATUS_INVALID_INFO_CLASS;
- case SystemRecommendedSharedDataAlignment: { len = sizeof(DWORD);
@@ -2773,6 +2869,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) || (is_win64 && query_len != sizeof(HANDLE)))
return STATUS_INVALID_PARAMETER;
I suspect these 64-bit differences are side-effects of the WoW translation rather than fundamental limitations. We may not be able to find a 32-bit Windows version to verify this, but there doesn't seem to be a reason to deliberately break these calls on 32-bit Wine.
On 3/29/21 22:33, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
@@ -2651,6 +2743,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, break; }
- case SystemCpuSetInformation:
return is_win64 ? NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size)
: STATUS_INVALID_INFO_CLASS;
- case SystemRecommendedSharedDataAlignment: { len = sizeof(DWORD);
@@ -2773,6 +2869,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) || (is_win64 && query_len != sizeof(HANDLE)))
return STATUS_INVALID_PARAMETER;
I suspect these 64-bit differences are side-effects of the WoW translation rather than fundamental limitations. We may not be able to find a 32-bit Windows version to verify this, but there doesn't seem to be a reason to deliberately break these calls on 32-bit Wine.
As for the first difference (NtQuerySystemInformation), it is just a matter of return error value, it doesn't work on neither 64 nor 32 bit as seems to always require NtQuerySystemInformationEx() to pass the process handle through its parameters. NtQuerySystemInformationEx() should work on 32 bit Wine as well.
As for the second condition in NtQuerySystemInformationEx(), as far as my testing goes on Windows 32bit (wow64) it allows bigger query len than sizeof(HANDLE) and still succeeds while on win64 requires the exact match, so it still works on 32 bit Wine.
Or did I misunderstand the concern?
Paul Gofman pgofman@codeweavers.com writes:
On 3/29/21 22:33, Alexandre Julliard wrote:
Paul Gofman pgofman@codeweavers.com writes:
@@ -2651,6 +2743,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, break; }
- case SystemCpuSetInformation:
return is_win64 ? NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size)
: STATUS_INVALID_INFO_CLASS;
- case SystemRecommendedSharedDataAlignment: { len = sizeof(DWORD);
@@ -2773,6 +2869,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) || (is_win64 && query_len != sizeof(HANDLE)))
return STATUS_INVALID_PARAMETER;
I suspect these 64-bit differences are side-effects of the WoW translation rather than fundamental limitations. We may not be able to find a 32-bit Windows version to verify this, but there doesn't seem to be a reason to deliberately break these calls on 32-bit Wine.
As for the first difference (NtQuerySystemInformation), it is just a matter of return error value, it doesn't work on neither 64 nor 32 bit as seems to always require NtQuerySystemInformationEx() to pass the process handle through its parameters. NtQuerySystemInformationEx() should work on 32 bit Wine as well.
As for the second condition in NtQuerySystemInformationEx(), as far as my testing goes on Windows 32bit (wow64) it allows bigger query len than sizeof(HANDLE) and still succeeds while on win64 requires the exact match, so it still works on 32 bit Wine.
Or did I misunderstand the concern?
The concern is having explicit is_win64 checks, we shouldn't need that. Just pick the behavior that makes the most sense.