diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index d552e5b81d8..2e30ebc9067 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -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 ); } diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 0504fc9cc5d..3936d5a8400 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -563,8 +563,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr ) 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, @@ -582,7 +580,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr ) 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 );