[Memory/CPU] UWP: Support separate code execution and write memory, FromApp functions + other Windows memory fixes
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user