[PATCH v2 0/4] MR10526: ntdll: Implement NtQuerySystemInformation(SystemSupportedProcessorArchitectures2).
`SystemSupportedProcessorArchitectures2` was added in Windows 11. As far as I can tell, the only difference between `SystemSupportedProcessorArchitectures` and `SystemSupportedProcessorArchitectures2` is on ARM64, where `SystemSupportedProcessorArchitectures` does not return x86_64 as a supported architecture. If you get `SystemSupportedProcessorArchitectures` for an emulated x86_64 process, it reports being an ARM64 process. `SystemSupportedProcessorArchitectures2` returns all 3 architectures, with flags set as expected. The ultimate goal here is to implement `GetMachineTypeAttributes()`, which Steam needs to correctly use the x86_64 version on ARM64. -- v2: server: Add x86_64 as a supported machine on ARM64. ntdll: Implement NtQuerySystemInformation(SystemSupportedProcessorArchitectures2). ntdll/tests: Add tests for NtQuerySystemInformation(SystemSupportedProcessorArchitectures2). ntdll/tests: In wow64, factor the SYSTEM_INFORMATION_CLASS out of test_query_architectures(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/tests/wow64.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 92d35d8647f..160979d2940 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -203,14 +203,14 @@ static BOOL create_process_machine( char *cmdline, DWORD flags, USHORT machine, return ret; } -static void test_process_architecture( HANDLE process, USHORT expect_machine, USHORT expect_native ) +static void test_process_architecture( SYSTEM_INFORMATION_CLASS class, HANDLE process, USHORT expect_machine, USHORT expect_native ) { SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION machines[8]; NTSTATUS status; ULONG i, len; len = 0xdead; - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), + status = pNtQuerySystemInformationEx( class, &process, sizeof(process), machines, sizeof(machines), &len ); ok( !status, "failed %lx\n", status ); ok( !(len & 3), "wrong len %lx\n", len ); @@ -234,7 +234,7 @@ static void test_process_architecture( HANDLE process, USHORT expect_machine, US ok( !*(DWORD *)&machines[i], "missing terminating null\n" ); len = i * sizeof(machines[0]); - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), + status = pNtQuerySystemInformationEx( class, &process, sizeof(process), machines, len, &len ); ok( status == STATUS_BUFFER_TOO_SMALL, "failed %lx\n", status ); ok( len == (i + 1) * sizeof(machines[0]), "wrong len %lu\n", len ); @@ -304,7 +304,7 @@ static void test_process_machine( HANDLE process, HANDLE thread, } } -static void test_query_architectures(void) +static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) { static char cmd_sysnative[] = "C:\\windows\\sysnative\\cmd.exe /c exit"; static char cmd_system32[] = "C:\\windows\\system32\\cmd.exe /c exit"; @@ -324,7 +324,7 @@ static void test_query_architectures(void) if (!pNtQuerySystemInformationEx) return; process = GetCurrentProcess(); - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), + status = pNtQuerySystemInformationEx( class, &process, sizeof(process), machines, sizeof(machines), &len ); if (status == STATUS_INVALID_INFO_CLASS) { @@ -334,39 +334,39 @@ static void test_query_architectures(void) ok( !status, "failed %lx\n", status ); process = (HANDLE)0xdeadbeef; - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process), + status = pNtQuerySystemInformationEx( class, &process, sizeof(process), machines, sizeof(machines), &len ); ok( status == STATUS_INVALID_HANDLE, "failed %lx\n", status ); process = (HANDLE)0xdeadbeef; - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, 3, + status = pNtQuerySystemInformationEx( class, &process, 3, machines, sizeof(machines), &len ); ok( status == STATUS_INVALID_PARAMETER || broken(status == STATUS_INVALID_HANDLE), "failed %lx\n", status ); process = GetCurrentProcess(); - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, 3, + status = pNtQuerySystemInformationEx( class, &process, 3, machines, sizeof(machines), &len ); ok( status == STATUS_INVALID_PARAMETER || broken( status == STATUS_SUCCESS), "failed %lx\n", status ); - status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, NULL, 0, + status = pNtQuerySystemInformationEx( class, NULL, 0, machines, sizeof(machines), &len ); ok( status == STATUS_INVALID_PARAMETER, "failed %lx\n", status ); winetest_push_context( "current" ); - test_process_architecture( GetCurrentProcess(), is_win64 ? native_machine : current_machine, + test_process_architecture( class, GetCurrentProcess(), is_win64 ? native_machine : current_machine, native_machine ); test_process_machine( GetCurrentProcess(), GetCurrentThread(), current_machine, is_arm64ec ? native_machine : current_machine ); winetest_pop_context(); winetest_push_context( "zero" ); - test_process_architecture( 0, 0, native_machine ); + test_process_architecture( class, 0, 0, native_machine ); winetest_pop_context(); if (CreateProcessA( NULL, is_win64 ? cmd_system32 : cmd_sysnative, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi )) { winetest_push_context( "system32" ); - test_process_architecture( pi.hProcess, native_machine, native_machine ); + test_process_architecture( class, pi.hProcess, native_machine, native_machine ); test_process_machine( pi.hProcess, pi.hThread, is_win64 ? current_machine : native_machine, native_machine ); TerminateProcess( pi.hProcess, 0 ); @@ -378,7 +378,7 @@ static void test_query_architectures(void) FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi )) { winetest_push_context( "syswow64" ); - test_process_architecture( pi.hProcess, IMAGE_FILE_MACHINE_I386, native_machine ); + test_process_architecture( class, pi.hProcess, IMAGE_FILE_MACHINE_I386, native_machine ); test_process_machine( pi.hProcess, pi.hThread, IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_I386 ); TerminateProcess( pi.hProcess, 0 ); CloseHandle( pi.hProcess ); @@ -392,7 +392,7 @@ static void test_query_architectures(void) if (create_process_machine( cmd_system32, CREATE_SUSPENDED, machine, &pi )) { winetest_push_context( "%04x", machine ); - test_process_architecture( pi.hProcess, native_machine, native_machine ); + test_process_architecture( class, pi.hProcess, native_machine, native_machine ); test_process_machine( pi.hProcess, pi.hThread, machine, native_machine ); TerminateProcess( pi.hProcess, 0 ); CloseHandle( pi.hProcess ); @@ -3212,7 +3212,7 @@ static void test_arm64ec(void) START_TEST(wow64) { init(); - test_query_architectures(); + test_query_architectures(SystemSupportedProcessorArchitectures); test_peb_teb(); test_selectors(); test_image_mappings(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/tests/wow64.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 160979d2940..59601c49563 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -153,8 +153,11 @@ static void init(void) { SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION machines[8]; HANDLE process = GetCurrentProcess(); - NTSTATUS status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, + NTSTATUS status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures2, &process, sizeof(process), machines, sizeof(machines), NULL ); + if (status) + status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, + sizeof(process), machines, sizeof(machines), NULL ); if (!status) for (int i = 0; machines[i].Machine; i++) trace( "machine %04x kernel %u user %u native %u process %u wow64 %u\n", @@ -209,6 +212,10 @@ static void test_process_architecture( SYSTEM_INFORMATION_CLASS class, HANDLE pr NTSTATUS status; ULONG i, len; + if (class == SystemSupportedProcessorArchitectures && + native_machine == IMAGE_FILE_MACHINE_ARM64 && expect_machine == IMAGE_FILE_MACHINE_AMD64) + expect_machine = IMAGE_FILE_MACHINE_ARM64; + len = 0xdead; status = pNtQuerySystemInformationEx( class, &process, sizeof(process), machines, sizeof(machines), &len ); @@ -230,6 +237,10 @@ static void test_process_architecture( SYSTEM_INFORMATION_CLASS class, HANDLE pr if (machines[i].WoW64Container) ok( is_machine_32bit( machines[i].Machine ) && !is_machine_32bit( native_machine ), "wrong wow64 %x\n", machines[i].Machine); + + if (class == SystemSupportedProcessorArchitectures && native_machine == IMAGE_FILE_MACHINE_ARM64) + ok( machines[i].Machine != IMAGE_FILE_MACHINE_AMD64, + "SystemSupportedProcessorArchitectures returned AMD64\n"); } ok( !*(DWORD *)&machines[i], "missing terminating null\n" ); @@ -244,7 +255,8 @@ static void test_process_architecture( SYSTEM_INFORMATION_CLASS class, HANDLE pr USHORT current = 0xdead, native = 0xbeef; status = pRtlWow64GetProcessMachines( process, ¤t, &native ); ok( !status, "failed %lx\n", status ); - if (expect_machine == expect_native) + if (expect_machine != IMAGE_FILE_MACHINE_I386 && + expect_machine != IMAGE_FILE_MACHINE_ARMNT) ok( current == 0, "wrong current machine %x / %x\n", current, expect_machine ); else ok( current == expect_machine, "wrong current machine %x / %x\n", current, expect_machine ); @@ -315,6 +327,7 @@ static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) NTSTATUS status; HANDLE process; ULONG i, len; + USHORT machine; #ifdef __arm64ec__ BOOL is_arm64ec = TRUE; #else @@ -328,7 +341,8 @@ static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) machines, sizeof(machines), &len ); if (status == STATUS_INVALID_INFO_CLASS) { - win_skip( "SystemSupportedProcessorArchitectures not supported\n" ); + win_skip( "SystemSupportedProcessorArchitectures%s not supported\n", + class == SystemSupportedProcessorArchitectures2 ? "2" : "" ); return; } ok( !status, "failed %lx\n", status ); @@ -352,7 +366,7 @@ static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) ok( status == STATUS_INVALID_PARAMETER, "failed %lx\n", status ); winetest_push_context( "current" ); - test_process_architecture( class, GetCurrentProcess(), is_win64 ? native_machine : current_machine, + test_process_architecture( class, GetCurrentProcess(), current_machine, native_machine ); test_process_machine( GetCurrentProcess(), GetCurrentThread(), current_machine, is_arm64ec ? native_machine : current_machine ); @@ -362,11 +376,11 @@ static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) test_process_architecture( class, 0, 0, native_machine ); winetest_pop_context(); - if (CreateProcessA( NULL, is_win64 ? cmd_system32 : cmd_sysnative, NULL, NULL, - FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi )) + machine = (is_win64 && native_machine == IMAGE_FILE_MACHINE_ARM64) ? current_machine : IMAGE_FILE_MACHINE_AMD64; + if (create_process_machine( is_win64 ? cmd_system32 : cmd_sysnative, CREATE_SUSPENDED, machine, &pi )) { winetest_push_context( "system32" ); - test_process_architecture( class, pi.hProcess, native_machine, native_machine ); + test_process_architecture( class, pi.hProcess, machine, native_machine ); test_process_machine( pi.hProcess, pi.hThread, is_win64 ? current_machine : native_machine, native_machine ); TerminateProcess( pi.hProcess, 0 ); @@ -392,7 +406,7 @@ static void test_query_architectures(SYSTEM_INFORMATION_CLASS class) if (create_process_machine( cmd_system32, CREATE_SUSPENDED, machine, &pi )) { winetest_push_context( "%04x", machine ); - test_process_architecture( class, pi.hProcess, native_machine, native_machine ); + test_process_architecture( class, pi.hProcess, machine, native_machine ); test_process_machine( pi.hProcess, pi.hThread, machine, native_machine ); TerminateProcess( pi.hProcess, 0 ); CloseHandle( pi.hProcess ); @@ -3213,6 +3227,7 @@ START_TEST(wow64) { init(); test_query_architectures(SystemSupportedProcessorArchitectures); + test_query_architectures(SystemSupportedProcessorArchitectures2); test_peb_teb(); test_selectors(); test_image_mappings(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/system.c | 33 +++++++++++++++++++++++++-------- dlls/wow64/system.c | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index aa66ec2654c..148624ff405 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -4091,11 +4091,14 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class, } case SystemSupportedProcessorArchitectures: + case SystemSupportedProcessorArchitectures2: { SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION *machines = info; HANDLE process; ULONG i; USHORT machine = 0; + USHORT machines_to_return[8]; + unsigned int machines_to_return_count = 0; if (!query || query_len < sizeof(HANDLE)) return STATUS_INVALID_PARAMETER; process = *(HANDLE *)query; @@ -4110,7 +4113,18 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class, if (ret) return ret; } - len = (supported_machines_count + 1) * sizeof(*machines); + for (i = 0; i < supported_machines_count; i++) + { +#ifdef __aarch64__ + if (class == SystemSupportedProcessorArchitectures && + supported_machines[i] == IMAGE_FILE_MACHINE_AMD64) + continue; +#endif + machines_to_return[machines_to_return_count] = supported_machines[i]; + machines_to_return_count++; + } + + len = (machines_to_return_count + 1) * sizeof(*machines); if (size < len) { ret = STATUS_BUFFER_TOO_SMALL; @@ -4119,20 +4133,23 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class, memset( machines, 0, len ); /* native machine */ - machines[0].Machine = supported_machines[0]; + machines[0].Machine = machines_to_return[0]; machines[0].UserMode = 1; machines[0].KernelMode = 1; machines[0].Native = 1; - machines[0].Process = (supported_machines[0] == machine || is_machine_64bit( machine )); + machines[0].Process = (machines_to_return[0] == machine || + (class == SystemSupportedProcessorArchitectures && + machine == IMAGE_FILE_MACHINE_AMD64)); machines[0].WoW64Container = 0; machines[0].ReservedZero0 = 0; - /* wow64 machines */ - for (i = 1; i < supported_machines_count; i++) + /* other machines */ + for (i = 1; i < machines_to_return_count; i++) { - machines[i].Machine = supported_machines[i]; + machines[i].Machine = machines_to_return[i]; machines[i].UserMode = 1; - machines[i].Process = supported_machines[i] == machine; - machines[i].WoW64Container = 1; + machines[i].Process = machines_to_return[i] == machine; + if (!is_machine_64bit( machines_to_return[i] )) + machines[i].WoW64Container = 1; } ret = STATUS_SUCCESS; break; diff --git a/dlls/wow64/system.c b/dlls/wow64/system.c index 335fed158c5..644c3ae9945 100644 --- a/dlls/wow64/system.c +++ b/dlls/wow64/system.c @@ -680,6 +680,7 @@ NTSTATUS WINAPI wow64_NtQuerySystemInformationEx( UINT *args ) case SystemCpuSetInformation: /* SYSTEM_CPU_SET_INFORMATION */ case SystemSupportedProcessorArchitectures: /* SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION */ + case SystemSupportedProcessorArchitectures2: /* SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION */ if (!query || query_len < sizeof(LONG)) return STATUS_INVALID_PARAMETER; handle = LongToHandle( *(LONG *)query ); return NtQuerySystemInformationEx( class, &handle, sizeof(handle), ptr, len, retlen ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
From: Brendan Shanks <bshanks@codeweavers.com> --- server/object.h | 5 ++--- server/registry.c | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/object.h b/server/object.h index cab8ad25a59..4d96740de03 100644 --- a/server/object.h +++ b/server/object.h @@ -287,9 +287,8 @@ static inline int is_machine_64bit( unsigned short machine ) } static inline int is_machine_supported( unsigned short machine ) { - unsigned int i; - for (i = 0; i < supported_machines_count; i++) if (supported_machines[i] == machine) return 1; - if (native_machine == IMAGE_FILE_MACHINE_ARM64) return machine == IMAGE_FILE_MACHINE_AMD64; + for (unsigned int i = 0; i < supported_machines_count; i++) + if (supported_machines[i] == machine) return 1; return 0; } diff --git a/server/registry.c b/server/registry.c index a367d70c7ee..91b3265e8f7 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1877,6 +1877,7 @@ static void init_supported_machines(void) supported_machines[count++] = IMAGE_FILE_MACHINE_ARM64; supported_machines[count++] = IMAGE_FILE_MACHINE_I386; if (supports_aarch32()) supported_machines[count++] = IMAGE_FILE_MACHINE_ARMNT; + supported_machines[count++] = IMAGE_FILE_MACHINE_AMD64; } #else #error Unsupported machine -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
This merge request was approved by Alexandre Julliard. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10526
participants (3)
-
Alexandre Julliard (@julliard) -
Brendan Shanks -
Brendan Shanks (@bshanks)