[Memory/CPU] UWP: Support separate code execution and write memory, FromApp functions + other Windows memory fixes

This commit is contained in:
Triang3l
2020-11-24 22:18:50 +03:00
parent cabd28b9bb
commit a73592c2ef
15 changed files with 348 additions and 113 deletions

View File

@@ -42,6 +42,8 @@ DWORD ToWin32ProtectFlags(PageAccess access) {
return PAGE_READONLY;
case PageAccess::kReadWrite:
return PAGE_READWRITE;
case PageAccess::kExecuteReadOnly:
return PAGE_EXECUTE_READ;
case PageAccess::kExecuteReadWrite:
return PAGE_EXECUTE_READWRITE;
default:
@@ -63,6 +65,8 @@ PageAccess ToXeniaProtectFlags(DWORD access) {
return PageAccess::kReadOnly;
case PAGE_READWRITE:
return PageAccess::kReadWrite;
case PAGE_EXECUTE_READ:
return PageAccess::kExecuteReadOnly;
case PAGE_EXECUTE_READWRITE:
return PageAccess::kExecuteReadWrite;
default:
@@ -70,6 +74,17 @@ PageAccess ToXeniaProtectFlags(DWORD access) {
}
}
bool IsWritableExecutableMemorySupported() {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
return true;
#else
// To test FromApp functions on desktop, replace
// WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) with 0 in the #ifs and
// link to WindowsApp.lib.
return false;
#endif
}
void* AllocFixed(void* base_address, size_t length,
AllocationType allocation_type, PageAccess access) {
DWORD alloc_type = 0;
@@ -88,7 +103,12 @@ void* AllocFixed(void* base_address, size_t length,
break;
}
DWORD protect = ToWin32ProtectFlags(access);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
return VirtualAlloc(base_address, length, alloc_type, protect);
#else
return VirtualAllocFromApp(base_address, length, ULONG(alloc_type),
ULONG(protect));
#endif
}
bool DeallocFixed(void* base_address, size_t length,
@@ -115,13 +135,19 @@ bool Protect(void* base_address, size_t length, PageAccess access,
*out_old_access = PageAccess::kNoAccess;
}
DWORD new_protect = ToWin32ProtectFlags(access);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
DWORD old_protect = 0;
BOOL result = VirtualProtect(base_address, length, new_protect, &old_protect);
#else
ULONG old_protect = 0;
BOOL result = VirtualProtectFromApp(base_address, length, ULONG(new_protect),
&old_protect);
#endif
if (!result) {
return false;
}
if (out_old_access) {
*out_old_access = ToXeniaProtectFlags(old_protect);
*out_old_access = ToXeniaProtectFlags(DWORD(old_protect));
}
return true;
}
@@ -148,9 +174,14 @@ FileMappingHandle CreateFileMappingHandle(const std::filesystem::path& path,
DWORD protect =
ToWin32ProtectFlags(access) | (commit ? SEC_COMMIT : SEC_RESERVE);
auto full_path = "Local" / path;
return CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, protect,
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
return CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, protect,
static_cast<DWORD>(length >> 32),
static_cast<DWORD>(length), full_path.c_str());
#else
return CreateFileMappingFromApp(INVALID_HANDLE_VALUE, nullptr, ULONG(protect),
ULONG64(length), full_path.c_str());
#endif
}
void CloseFileMappingHandle(FileMappingHandle handle,
@@ -160,6 +191,7 @@ void CloseFileMappingHandle(FileMappingHandle handle,
void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
PageAccess access, size_t file_offset) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
DWORD target_address_low = static_cast<DWORD>(file_offset);
DWORD target_address_high = static_cast<DWORD>(file_offset >> 32);
DWORD file_access = 0;
@@ -170,6 +202,9 @@ void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
case PageAccess::kReadWrite:
file_access = FILE_MAP_ALL_ACCESS;
break;
case PageAccess::kExecuteReadOnly:
file_access = FILE_MAP_READ | FILE_MAP_EXECUTE;
break;
case PageAccess::kExecuteReadWrite:
file_access = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE;
break;
@@ -180,6 +215,25 @@ void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
}
return MapViewOfFileEx(handle, file_access, target_address_high,
target_address_low, length, base_address);
#else
// VirtualAlloc2FromApp and MapViewOfFile3FromApp were added in 10.0.17134.0.
// https://docs.microsoft.com/en-us/uwp/win32-and-com/win32-apis
HANDLE process = GetCurrentProcess();
void* placeholder = VirtualAlloc2FromApp(
process, base_address, length, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
PAGE_NOACCESS, nullptr, 0);
if (!placeholder) {
return nullptr;
}
void* mapping = MapViewOfFile3FromApp(
handle, process, placeholder, ULONG64(file_offset), length,
MEM_REPLACE_PLACEHOLDER, ULONG(ToWin32ProtectFlags(access)), nullptr, 0);
if (!mapping) {
VirtualFree(placeholder, length, MEM_RELEASE);
return nullptr;
}
return mapping;
#endif
}
bool UnmapFileView(FileMappingHandle handle, void* base_address,