wow64: Add thunks for the virtual memory syscalls.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-07-27 11:15:25 +02:00
parent a06bcd03b9
commit dffe2bf8e2
4 changed files with 290 additions and 1 deletions

View File

@ -7,4 +7,5 @@ EXTRADLLFLAGS = -nodefaultlibs -mno-cygwin -Wl,--image-base,0x6f000000
C_SRCS = \
registry.c \
sync.c \
syscall.c
syscall.c \
virtual.c

View File

@ -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 */

255
dlls/wow64/virtual.c Normal file
View File

@ -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 <stdarg.h>
#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;
}

View File

@ -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 );