Needed for GOG Galaxy.
-- v3: ntdll: Implement NtWow64QueryInformationProcess64.
From: Alex Henrie dhenrale@amazon.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48235 --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/ntsyscalls.h | 17 ++++++----- dlls/ntdll/tests/wow64.c | 48 ++++++++++++++++++++++++++++++ dlls/ntdll/unix/process.c | 62 +++++++++++++++++++++++++++++++++++++++ dlls/wow64/syscall.c | 21 +++++++++++++ include/winternl.h | 12 ++++++++ 6 files changed, 153 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5fe8dcc4a0b..ddf1a120517 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -451,6 +451,7 @@ @ stdcall -syscall -arch=win32 NtWow64AllocateVirtualMemory64(long ptr int64 ptr long long) @ stdcall -syscall -arch=win32 NtWow64GetNativeSystemInformation(long ptr long ptr) @ stdcall -syscall -arch=win32 NtWow64IsProcessorFeaturePresent(long) +@ stdcall -syscall -arch=win32 NtWow64QueryInformationProcess64(long long ptr long ptr) @ stdcall -syscall -arch=win32 NtWow64ReadVirtualMemory64(long int64 ptr int64 ptr) @ stdcall -syscall -arch=win32 NtWow64WriteVirtualMemory64(long int64 ptr int64 ptr) @ stdcall -syscall NtWriteFile(long long ptr ptr ptr ptr long ptr ptr) diff --git a/dlls/ntdll/ntsyscalls.h b/dlls/ntdll/ntsyscalls.h index 78d602ac5dc..b03002b7cd8 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -236,14 +236,15 @@ SYSCALL_ENTRY( 0x00e8, NtWow64AllocateVirtualMemory64, 28 ) \ SYSCALL_ENTRY( 0x00e9, NtWow64GetNativeSystemInformation, 16 ) \ SYSCALL_ENTRY( 0x00ea, NtWow64IsProcessorFeaturePresent, 4 ) \ - SYSCALL_ENTRY( 0x00eb, NtWow64ReadVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00ec, NtWow64WriteVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00ed, NtWriteFile, 36 ) \ - SYSCALL_ENTRY( 0x00ee, NtWriteFileGather, 36 ) \ - SYSCALL_ENTRY( 0x00ef, NtWriteVirtualMemory, 20 ) \ - SYSCALL_ENTRY( 0x00f0, NtYieldExecution, 0 ) \ - SYSCALL_ENTRY( 0x00f1, wine_nt_to_unix_file_name, 16 ) \ - SYSCALL_ENTRY( 0x00f2, wine_unix_to_nt_file_name, 12 ) + SYSCALL_ENTRY( 0x00eb, NtWow64QueryInformationProcess64, 20 ) \ + SYSCALL_ENTRY( 0x00ec, NtWow64ReadVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x00ed, NtWow64WriteVirtualMemory64, 28 ) \ + SYSCALL_ENTRY( 0x00ee, NtWriteFile, 36 ) \ + SYSCALL_ENTRY( 0x00ef, NtWriteFileGather, 36 ) \ + SYSCALL_ENTRY( 0x00f0, NtWriteVirtualMemory, 20 ) \ + SYSCALL_ENTRY( 0x00f1, NtYieldExecution, 0 ) \ + SYSCALL_ENTRY( 0x00f2, wine_nt_to_unix_file_name, 16 ) \ + SYSCALL_ENTRY( 0x00f3, wine_unix_to_nt_file_name, 12 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 054e5fac6e9..ee16dfc0e26 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -56,6 +56,7 @@ static void (WINAPI *pProcessPendingCrossProcessEmulatorWork)(void); static NTSTATUS (WINAPI *pNtWow64AllocateVirtualMemory64)(HANDLE,ULONG64*,ULONG64,ULONG64*,ULONG,ULONG); static NTSTATUS (WINAPI *pNtWow64GetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*); static NTSTATUS (WINAPI *pNtWow64IsProcessorFeaturePresent)(ULONG); +static NTSTATUS (WINAPI *pNtWow64QueryInformationProcess64)(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*); static NTSTATUS (WINAPI *pNtWow64ReadVirtualMemory64)(HANDLE,ULONG64,void*,ULONG64,ULONG64*); static NTSTATUS (WINAPI *pNtWow64WriteVirtualMemory64)(HANDLE,ULONG64,const void *,ULONG64,ULONG64*); #endif @@ -140,6 +141,7 @@ static void init(void) GET_PROC( NtWow64AllocateVirtualMemory64 ); GET_PROC( NtWow64GetNativeSystemInformation ); GET_PROC( NtWow64IsProcessorFeaturePresent ); + GET_PROC( NtWow64QueryInformationProcess64 ); GET_PROC( NtWow64ReadVirtualMemory64 ); GET_PROC( NtWow64WriteVirtualMemory64 ); #endif @@ -2595,6 +2597,52 @@ static void test_nt_wow64(void) } else win_skip( "NtWow64IsProcessorFeaturePresent not supported\n" );
+ if (pNtWow64QueryInformationProcess64) + { + PROCESS_BASIC_INFORMATION pbi32; + PROCESS_BASIC_INFORMATION64 pbi64; + ULONG expected_peb; + ULONG class; + + for (class = 0; class <= MaxProcessInfoClass; class++) + { + winetest_push_context( "Process information class %lu", class ); + + switch (class) + { + case ProcessBasicInformation: + status = NtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi32, sizeof(pbi32), NULL ); + ok( !status, "NtQueryInformationProcess returned 0x%08lx\n", status ); + + status = NtWow64QueryInformationProcess64( GetCurrentProcess(), ProcessBasicInformation, &pbi64, sizeof(pbi64), NULL ); + ok( !status, "NtWow64QueryInformationProcess64 returned 0x%08lx\n", status ); + + expected_peb = (ULONG)pbi32.PebBaseAddress; + if (is_wow64) expected_peb -= 0x1000; + + ok( pbi64.ExitStatus == pbi32.ExitStatus, + "expected %lu got %lu\n", pbi32.ExitStatus, pbi64.ExitStatus ); + ok( pbi64.PebBaseAddress == expected_peb || + /* The 64-bit PEB is usually, but not always, 4096 bytes below the 32-bit PEB */ + broken( is_wow64 && llabs( (INT64)pbi64.PebBaseAddress - (INT64)expected_peb ) < 0x10000 ), + "expected 0x%lx got 0x%llx\n", expected_peb, pbi64.PebBaseAddress ); + ok( pbi64.AffinityMask == pbi32.AffinityMask, + "expected 0x%lx got 0x%llx\n", pbi32.AffinityMask, pbi64.AffinityMask ); + ok( pbi64.UniqueProcessId == pbi32.UniqueProcessId, + "expected %ld got %lld\n", pbi32.UniqueProcessId, pbi64.UniqueProcessId ); + ok( pbi64.InheritedFromUniqueProcessId == pbi32.InheritedFromUniqueProcessId, + "expected %ld got %lld\n", pbi32.UniqueProcessId, pbi64.UniqueProcessId ); + break; + default: + status = NtWow64QueryInformationProcess64( GetCurrentProcess(), class, NULL, 0, NULL ); + ok( status == STATUS_NOT_IMPLEMENTED, "NtWow64QueryInformationProcess64 returned 0x%08lx\n", status ); + } + + winetest_pop_context(); + } + } + else win_skip( "NtWow64QueryInformationProcess64 not supported\n" ); + NtClose( process ); }
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index f3551c2e7d7..ec585fe2d6c 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -1617,6 +1617,68 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class return ret; }
+#ifndef _WIN64 + +/********************************************************************** + * NtWow64QueryInformationProcess64 (NTDLL.@) + */ +NTSTATUS WINAPI NtWow64QueryInformationProcess64( HANDLE handle, PROCESSINFOCLASS class, void *info, + ULONG size, ULONG *ret_len ) +{ + NTSTATUS ret; + ULONG len = 0; + + TRACE( "(%p,0x%08x,%p,0x%08x,%p)\n", handle, class, info, (int)size, ret_len ); + + switch (class) + { + case ProcessBasicInformation: + { + PROCESS_BASIC_INFORMATION64 pbi; + const ULONG_PTR affinity_mask = get_system_affinity_mask(); + + if (size >= sizeof(PROCESS_BASIC_INFORMATION64)) + { + if (!info) ret = STATUS_ACCESS_VIOLATION; + else + { + SERVER_START_REQ(get_process_info) + { + req->handle = wine_server_obj_handle( handle ); + if ((ret = wine_server_call( req )) == STATUS_SUCCESS) + { + pbi.ExitStatus = reply->exit_code; + pbi.PebBaseAddress = (ULONG)wine_server_get_ptr( reply->peb ); + pbi.AffinityMask = reply->affinity & affinity_mask; + pbi.BasePriority = reply->priority; + pbi.UniqueProcessId = reply->pid; + pbi.InheritedFromUniqueProcessId = reply->ppid; + } + } + SERVER_END_REQ; + + memcpy( info, &pbi, sizeof(PROCESS_BASIC_INFORMATION64) ); + len = sizeof(PROCESS_BASIC_INFORMATION64); + } + if (size > sizeof(PROCESS_BASIC_INFORMATION64)) ret = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + len = sizeof(PROCESS_BASIC_INFORMATION64); + ret = STATUS_INFO_LENGTH_MISMATCH; + } + } + break; + + default: + return STATUS_NOT_IMPLEMENTED; + } + + if (ret_len) *ret_len = len; + return ret; +} + +#endif
/********************************************************************** * NtSetInformationProcess (NTDLL.@) diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index 790656b311e..77a71972868 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -679,6 +679,27 @@ NTSTATUS WINAPI wow64_NtWow64IsProcessorFeaturePresent( UINT *args ) }
+/********************************************************************** + * wow64_NtWow64QueryInformationProcess64 + */ +NTSTATUS WINAPI wow64_NtWow64QueryInformationProcess64( UINT *args ) +{ + HANDLE handle = get_ptr( &args ); + PROCESSINFOCLASS class = get_ulong( &args ); + void *info = get_ptr( &args ); + ULONG size = get_ulong( &args ); + ULONG *ret_len = get_ptr( &args ); + + switch (class) + { + case ProcessBasicInformation: + return NtQueryInformationProcess( handle, class, info, size, ret_len ); + default: + return STATUS_NOT_IMPLEMENTED; + } +} + + /********************************************************************** * init_image_mapping */ diff --git a/include/winternl.h b/include/winternl.h index 53f11b18486..e7e589684f5 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2642,6 +2642,17 @@ typedef struct _PROCESS_BASIC_INFORMATION { #endif } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
+#ifdef __WINESRC__ +typedef struct _PROCESS_BASIC_INFORMATION64 { + NTSTATUS ExitStatus; + UINT64 PebBaseAddress; + UINT64 AffinityMask; + LONG BasePriority; + UINT64 UniqueProcessId; + UINT64 InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION64; +#endif + #define PROCESS_PRIOCLASS_IDLE 1 #define PROCESS_PRIOCLASS_NORMAL 2 #define PROCESS_PRIOCLASS_HIGH 3 @@ -5177,6 +5188,7 @@ NTSYSAPI NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE,const WOW64_CONTEXT*); NTSYSAPI NTSTATUS WINAPI NtWow64AllocateVirtualMemory64(HANDLE,ULONG64*,ULONG64,ULONG64*,ULONG,ULONG); NTSYSAPI NTSTATUS WINAPI NtWow64GetNativeSystemInformation(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI NtWow64IsProcessorFeaturePresent(UINT); +NTSYSAPI NTSTATUS WINAPI NtWow64QueryInformationProcess64(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI NtWow64ReadVirtualMemory64(HANDLE,ULONG64,void*,ULONG64,ULONG64*); NTSYSAPI NTSTATUS WINAPI NtWow64WriteVirtualMemory64(HANDLE,ULONG64,const void*,ULONG64,ULONG64*); NTSYSAPI LONGLONG WINAPI RtlConvertLongToLargeInteger(LONG);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149165
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000035C00E0, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
On Mon Oct 21 20:07:41 2024 +0000, Elizabeth Figura wrote:
I'm looking at these failures: https://testbot.winehq.org/JobDetails.pl?Key=149069
Thanks. It looks like the PEB location is not perfectly predictable. I've marked it as broken but acceptable if Windows returns a value within 64 KiB of the expected value.
Let me know if you want a `skip` for Wine's new-wow64 mode too.
This merge request was approved by Elizabeth Figura.