From dffe2bf8e225ec3f92c210ba6d4777cd675ea146 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 27 Jul 2021 11:15:25 +0200 Subject: [PATCH] wow64: Add thunks for the virtual memory syscalls. Signed-off-by: Alexandre Julliard --- dlls/wow64/Makefile.in | 3 +- dlls/wow64/syscall.h | 9 ++ dlls/wow64/virtual.c | 255 +++++++++++++++++++++++++++++++++++++ dlls/wow64/wow64_private.h | 24 ++++ 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 dlls/wow64/virtual.c diff --git a/dlls/wow64/Makefile.in b/dlls/wow64/Makefile.in index 4ab1b088dff..693fdefaae4 100644 --- a/dlls/wow64/Makefile.in +++ b/dlls/wow64/Makefile.in @@ -7,4 +7,5 @@ EXTRADLLFLAGS = -nodefaultlibs -mno-cygwin -Wl,--image-base,0x6f000000 C_SRCS = \ registry.c \ sync.c \ - syscall.c + syscall.c \ + virtual.c diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index ccb4f02c91e..23d36ff3992 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -26,6 +26,8 @@ SYSCALL_ENTRY( NtAddAtom ) \ SYSCALL_ENTRY( NtAllocateLocallyUniqueId ) \ SYSCALL_ENTRY( NtAllocateUuids ) \ + SYSCALL_ENTRY( NtAllocateVirtualMemory ) \ + SYSCALL_ENTRY( NtAllocateVirtualMemoryEx ) \ SYSCALL_ENTRY( NtCancelTimer ) \ SYSCALL_ENTRY( NtClearEvent ) \ SYSCALL_ENTRY( NtClearPowerRequest ) \ @@ -57,10 +59,13 @@ SYSCALL_ENTRY( NtEnumerateValueKey ) \ SYSCALL_ENTRY( NtFindAtom ) \ SYSCALL_ENTRY( NtFlushKey ) \ + SYSCALL_ENTRY( NtFlushVirtualMemory ) \ + SYSCALL_ENTRY( NtFreeVirtualMemory ) \ SYSCALL_ENTRY( NtGetCurrentProcessorNumber ) \ SYSCALL_ENTRY( NtListenPort ) \ SYSCALL_ENTRY( NtLoadKey ) \ SYSCALL_ENTRY( NtLoadKey2 ) \ + SYSCALL_ENTRY( NtLockVirtualMemory ) \ SYSCALL_ENTRY( NtMakeTemporaryObject ) \ SYSCALL_ENTRY( NtOpenDirectoryObject ) \ SYSCALL_ENTRY( NtOpenEvent ) \ @@ -76,6 +81,7 @@ SYSCALL_ENTRY( NtOpenSemaphore ) \ SYSCALL_ENTRY( NtOpenSymbolicLinkObject ) \ SYSCALL_ENTRY( NtOpenTimer ) \ + SYSCALL_ENTRY( NtProtectVirtualMemory ) \ SYSCALL_ENTRY( NtPulseEvent ) \ SYSCALL_ENTRY( NtQueryDefaultLocale ) \ SYSCALL_ENTRY( NtQueryDefaultUILanguage ) \ @@ -95,6 +101,7 @@ SYSCALL_ENTRY( NtQueryTimer ) \ SYSCALL_ENTRY( NtQueryTimerResolution ) \ SYSCALL_ENTRY( NtQueryValueKey ) \ + SYSCALL_ENTRY( NtReadVirtualMemory ) \ SYSCALL_ENTRY( NtReleaseKeyedEvent ) \ SYSCALL_ENTRY( NtReleaseMutant ) \ SYSCALL_ENTRY( NtReleaseSemaphore ) \ @@ -120,10 +127,12 @@ SYSCALL_ENTRY( NtSignalAndWaitForSingleObject ) \ SYSCALL_ENTRY( NtTerminateJobObject ) \ SYSCALL_ENTRY( NtUnloadKey ) \ + SYSCALL_ENTRY( NtUnlockVirtualMemory ) \ SYSCALL_ENTRY( NtWaitForDebugEvent ) \ SYSCALL_ENTRY( NtWaitForKeyedEvent ) \ SYSCALL_ENTRY( NtWaitForMultipleObjects ) \ SYSCALL_ENTRY( NtWaitForSingleObject ) \ + SYSCALL_ENTRY( NtWriteVirtualMemory ) \ SYSCALL_ENTRY( NtYieldExecution ) #endif /* __WOW64_SYSCALL_H */ diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c new file mode 100644 index 00000000000..aa680a5fd26 --- /dev/null +++ b/dlls/wow64/virtual.c @@ -0,0 +1,255 @@ +/* + * WoW64 virtual memory functions + * + * Copyright 2021 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winnt.h" +#include "winternl.h" +#include "winioctl.h" +#include "wow64_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wow); + + +/********************************************************************** + * wow64_NtAllocateVirtualMemory + */ +NTSTATUS WINAPI wow64_NtAllocateVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG_PTR zero_bits = get_ulong( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG type = get_ulong( &args ); + ULONG protect = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtAllocateVirtualMemory( process, addr_32to64( &addr, addr32 ), get_zero_bits( zero_bits ), + size_32to64( &size, size32 ), type, protect ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtAllocateVirtualMemoryEx + */ +NTSTATUS WINAPI wow64_NtAllocateVirtualMemoryEx( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG type = get_ulong( &args ); + ULONG protect = get_ulong( &args ); + MEM_EXTENDED_PARAMETER *params = get_ptr( &args ); + ULONG count = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + if (count) FIXME( "%d extended parameters %p\n", count, params ); + status = NtAllocateVirtualMemoryEx( process, addr_32to64( &addr, addr32 ), size_32to64( &size, size32 ), + type, protect, params, count ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtFlushVirtualMemory + */ +NTSTATUS WINAPI wow64_NtFlushVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG unknown = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtFlushVirtualMemory( process, (const void **)addr_32to64( &addr, addr32 ), + size_32to64( &size, size32 ), unknown ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtFreeVirtualMemory + */ +NTSTATUS WINAPI wow64_NtFreeVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG type = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtFreeVirtualMemory( process, addr_32to64( &addr, addr32 ), + size_32to64( &size, size32 ), type ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtLockVirtualMemory + */ +NTSTATUS WINAPI wow64_NtLockVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG unknown = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtLockVirtualMemory( process, addr_32to64( &addr, addr32 ), + size_32to64( &size, size32 ), unknown ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtProtectVirtualMemory + */ +NTSTATUS WINAPI wow64_NtProtectVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG new_prot = get_ulong( &args ); + ULONG *old_prot = get_ptr( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtProtectVirtualMemory( process, addr_32to64( &addr, addr32 ), + size_32to64( &size, size32 ), new_prot, old_prot ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtReadVirtualMemory + */ +NTSTATUS WINAPI wow64_NtReadVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + const void *addr = get_ptr( &args ); + void *buffer = get_ptr( &args ); + SIZE_T size = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + SIZE_T ret_size; + NTSTATUS status; + + status = NtReadVirtualMemory( process, addr, buffer, size, &ret_size ); + put_size( retlen, ret_size ); + return status; +} + + +/********************************************************************** + * wow64_NtUnlockVirtualMemory + */ +NTSTATUS WINAPI wow64_NtUnlockVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + ULONG *addr32 = get_ptr( &args ); + ULONG *size32 = get_ptr( &args ); + ULONG unknown = get_ulong( &args ); + + void *addr; + SIZE_T size; + NTSTATUS status; + + status = NtUnlockVirtualMemory( process, addr_32to64( &addr, addr32 ), + size_32to64( &size, size32 ), unknown ); + if (!status) + { + put_addr( addr32, addr ); + put_size( size32, size ); + } + return status; +} + + +/********************************************************************** + * wow64_NtWriteVirtualMemory + */ +NTSTATUS WINAPI wow64_NtWriteVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + void *addr = get_ptr( &args ); + const void *buffer = get_ptr( &args ); + SIZE_T size = get_ulong( &args ); + ULONG *retlen = get_ptr( &args ); + + SIZE_T ret_size; + NTSTATUS status; + + status = NtWriteVirtualMemory( process, addr, buffer, size, &ret_size ); + put_size( retlen, ret_size ); + return status; +} diff --git a/dlls/wow64/wow64_private.h b/dlls/wow64/wow64_private.h index c456c0d9352..f4d195f06fb 100644 --- a/dlls/wow64/wow64_private.h +++ b/dlls/wow64/wow64_private.h @@ -63,6 +63,25 @@ static inline ULONG get_ulong( UINT **args ) { return *(*args)++; } static inline HANDLE get_handle( UINT **args ) { return LongToHandle( *(*args)++ ); } static inline void *get_ptr( UINT **args ) { return ULongToPtr( *(*args)++ ); } +static inline ULONG_PTR get_zero_bits( ULONG_PTR zero_bits ) +{ + return zero_bits ? zero_bits : 0x7fffffff; +} + +static inline void **addr_32to64( void **addr, ULONG *addr32 ) +{ + if (!addr32) return NULL; + *addr = ULongToPtr( *addr32 ); + return addr; +} + +static inline SIZE_T *size_32to64( SIZE_T *size, ULONG *size32 ) +{ + if (!size32) return NULL; + *size = *size32; + return size; +} + static inline void *apc_32to64( ULONG func ) { return func ? Wow64ApcRoutine : NULL; @@ -137,6 +156,11 @@ static inline void put_handle( ULONG *handle32, HANDLE handle ) *handle32 = HandleToULong( handle ); } +static inline void put_addr( ULONG *addr32, void *addr ) +{ + if (addr32) *addr32 = PtrToUlong( addr ); +} + static inline void put_size( ULONG *size32, SIZE_T size ) { if (size32) *size32 = min( size, MAXDWORD );