mirror of
https://github.com/wine-mirror/wine
synced 2024-07-01 07:14:31 +00:00
kernelbase: Send cross process notifications in WriteProcessMemory on ARM64.
This commit is contained in:
parent
6ea77ec086
commit
2c7f4181bc
|
@ -42,6 +42,53 @@ WINE_DECLARE_DEBUG_CHANNEL(virtual);
|
|||
WINE_DECLARE_DEBUG_CHANNEL(globalmem);
|
||||
|
||||
|
||||
|
||||
static CROSS_PROCESS_WORK_LIST *open_cross_process_connection( HANDLE process )
|
||||
{
|
||||
#ifdef __aarch64__
|
||||
CROSS_PROCESS_WORK_LIST *list;
|
||||
HANDLE section;
|
||||
|
||||
RtlOpenCrossProcessEmulatorWorkConnection( process, §ion, (void **)&list );
|
||||
if (section) NtClose( section );
|
||||
return list;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void close_cross_process_connection( CROSS_PROCESS_WORK_LIST *list )
|
||||
{
|
||||
if (list) NtUnmapViewOfSection( GetCurrentProcess(), list );
|
||||
}
|
||||
|
||||
static void send_cross_process_notification( CROSS_PROCESS_WORK_LIST *list, UINT id,
|
||||
const void *addr, SIZE_T size, int nb_args, ... )
|
||||
{
|
||||
#ifdef __aarch64__
|
||||
CROSS_PROCESS_WORK_ENTRY *entry;
|
||||
void *unused;
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
if (!list) return;
|
||||
if ((entry = RtlWow64PopCrossProcessWorkFromFreeList( &list->free_list )))
|
||||
{
|
||||
entry->id = id;
|
||||
entry->addr = (ULONG_PTR)addr;
|
||||
entry->size = size;
|
||||
if (nb_args)
|
||||
{
|
||||
va_start( args, nb_args );
|
||||
for (i = 0; i < nb_args; i++) entry->args[i] = va_arg( args, int );
|
||||
va_end( args );
|
||||
}
|
||||
RtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, entry, &unused );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Virtual memory functions
|
||||
***********************************************************************/
|
||||
|
@ -540,13 +587,18 @@ BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
|
|||
BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
|
||||
SIZE_T size, SIZE_T *bytes_written )
|
||||
{
|
||||
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
|
||||
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | PAGE_EXECUTE_WRITECOPY;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
void *base_addr;
|
||||
SIZE_T region_size;
|
||||
NTSTATUS status;
|
||||
NTSTATUS status, status2;
|
||||
|
||||
if (!VirtualQueryEx( process, addr, &info, sizeof(info) )) return FALSE;
|
||||
if (!VirtualQueryEx( process, addr, &info, sizeof(info) ))
|
||||
{
|
||||
close_cross_process_connection( list );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (info.Protect)
|
||||
{
|
||||
|
@ -556,6 +608,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
|
|||
case PAGE_EXECUTE_WRITECOPY:
|
||||
/* already writable */
|
||||
if ((status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ))) break;
|
||||
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
|
||||
NtFlushInstructionCache( process, addr, size );
|
||||
break;
|
||||
|
||||
|
@ -565,12 +618,27 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
|
|||
base_addr = ROUND_ADDR( addr );
|
||||
region_size = ROUND_SIZE( addr, size );
|
||||
region_size = min( region_size, (char *)info.BaseAddress + info.RegionSize - (char *)base_addr );
|
||||
|
||||
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
|
||||
base_addr, region_size, 1, prot );
|
||||
status = NtProtectVirtualMemory( process, &base_addr, ®ion_size, prot, &old_prot );
|
||||
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
|
||||
base_addr, region_size, 2, prot, status );
|
||||
if (status) break;
|
||||
|
||||
status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written );
|
||||
if (!status) NtFlushInstructionCache( process, addr, size );
|
||||
if (!status)
|
||||
{
|
||||
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
|
||||
NtFlushInstructionCache( process, addr, size );
|
||||
}
|
||||
|
||||
prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | old_prot;
|
||||
NtProtectVirtualMemory( process, &base_addr, ®ion_size, prot, &old_prot );
|
||||
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
|
||||
base_addr, region_size, 1, prot );
|
||||
status2 = NtProtectVirtualMemory( process, &base_addr, ®ion_size, prot, &old_prot );
|
||||
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
|
||||
base_addr, region_size, 2, prot, status2 );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -579,6 +647,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
|
|||
break;
|
||||
}
|
||||
|
||||
close_cross_process_connection( list );
|
||||
return set_ntstatus( status );
|
||||
}
|
||||
|
||||
|
|
|
@ -729,8 +729,6 @@ static void test_cross_process_notifications( HANDLE process, ULONG_PTR section,
|
|||
|
||||
WriteProcessMemory( process, (char *)addr + 0x1ffe, data, sizeof(data), &size );
|
||||
entry = pop_from_work_list( &list->work_list );
|
||||
todo_wine_if (current_machine == IMAGE_FILE_MACHINE_ARM64)
|
||||
{
|
||||
entry = expect_cross_work_entry( list, entry, CrossProcessPreVirtualProtect,
|
||||
(char *)addr + 0x1000, 0x2000, 0x60000000 | PAGE_EXECUTE_WRITECOPY,
|
||||
(current_machine != IMAGE_FILE_MACHINE_ARM64) ? 0 : 0xcccccccc,
|
||||
|
@ -748,7 +746,6 @@ static void test_cross_process_notifications( HANDLE process, ULONG_PTR section,
|
|||
entry = expect_cross_work_entry( list, entry, CrossProcessPostVirtualProtect,
|
||||
(char *)addr + 0x1000, 0x2000,
|
||||
0x60000000 | PAGE_EXECUTE_READ, 0, 0xcccccccc, 0xcccccccc );
|
||||
}
|
||||
ok( !entry, "not at end of list\n" );
|
||||
|
||||
status = NtUnmapViewOfSection( process, addr );
|
||||
|
|
Loading…
Reference in New Issue
Block a user