Needed for GOG Galaxy.
-- v2: 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 | 46 +++++++++++++++++++++++++++++ dlls/ntdll/unix/process.c | 62 +++++++++++++++++++++++++++++++++++++++ dlls/wow64/syscall.c | 21 +++++++++++++ include/winternl.h | 12 ++++++++ 6 files changed, 151 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1234205cf1a..d42c94af591 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -450,6 +450,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 55e1436848b..4efc20bebaa 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -235,14 +235,15 @@ SYSCALL_ENTRY( 0x00e7, NtWow64AllocateVirtualMemory64, 28 ) \ SYSCALL_ENTRY( 0x00e8, NtWow64GetNativeSystemInformation, 16 ) \ SYSCALL_ENTRY( 0x00e9, NtWow64IsProcessorFeaturePresent, 4 ) \ - SYSCALL_ENTRY( 0x00ea, NtWow64ReadVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00eb, NtWow64WriteVirtualMemory64, 28 ) \ - SYSCALL_ENTRY( 0x00ec, NtWriteFile, 36 ) \ - SYSCALL_ENTRY( 0x00ed, NtWriteFileGather, 36 ) \ - SYSCALL_ENTRY( 0x00ee, NtWriteVirtualMemory, 20 ) \ - SYSCALL_ENTRY( 0x00ef, NtYieldExecution, 0 ) \ - SYSCALL_ENTRY( 0x00f0, wine_nt_to_unix_file_name, 16 ) \ - SYSCALL_ENTRY( 0x00f1, wine_unix_to_nt_file_name, 12 ) + SYSCALL_ENTRY( 0x00ea, NtWow64QueryInformationProcess64, 20 ) \ + 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 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 054e5fac6e9..93de5e53d84 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,50 @@ 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, "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 fc60ae37816..61a033213f2 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -662,6 +662,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 4f24a921bb1..600057fc8ed 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2636,6 +2636,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 @@ -5170,6 +5181,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=149069
Your paranoid android.
=== w864 (32 bit report) ===
ntdll: wow64.c:2625: Test failed: Process information class 0: expected 0x7e95d000 got 0x7e954000
=== w1064v1507 (32 bit report) ===
ntdll: wow64.c:2625: Test failed: Process information class 0: expected 0x7efd8000 got 0x7efde000
On Thu Oct 17 09:35:48 2024 +0000, Alexandre Julliard wrote:
Calling NtQueryInformationProcess is the right thing to do (except you'd need to check the info class).
You're right: On 64-bit, NtQueryInformationProcess behaves the same as NtWow64QueryInformationProcess64. We just need to filter out info classes other than ProcessBasicInformation. Fixed.
Marvin is reporting failures here; looks like the PEB address doesn't actually match?
On Mon Oct 21 18:58:45 2024 +0000, Elizabeth Figura wrote:
Marvin is reporting failures here; looks like the PEB address doesn't actually match?
I am not seeing any PEB-related failures (if I'm just bad at finding them then please point them out), but I am seeing failures in new-wow64 mode because GetCurrentProcess() returns INVALID_HANDLE_VALUE. Is that to be expected? I guess I should add a `skip` statement to document the problem.
On Mon Oct 21 18:58:45 2024 +0000, Alex Henrie wrote:
I am not seeing any PEB-related failures (if I'm just bad at finding them then please point them out), but I am seeing failures in new-wow64 mode because GetCurrentProcess() returns INVALID_HANDLE_VALUE. Is that to be expected? I guess I should add a `skip` statement to document the problem.
I'm looking at these failures: