From 88be0a362c83630f5fb13d9906cfdb9497e32a27 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Thu, 22 Oct 2015 20:16:27 -0500 Subject: [PATCH] memory::QueryProtect --- src/xenia/base/memory.h | 6 ++++ src/xenia/base/memory_win.cc | 54 +++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h index 52aeb8ad3..a5c337383 100644 --- a/src/xenia/base/memory.h +++ b/src/xenia/base/memory.h @@ -63,6 +63,12 @@ bool DeallocFixed(void* base_address, size_t length, bool Protect(void* base_address, size_t length, PageAccess access, PageAccess* out_old_access); +// Queries a region of pages to get the access rights. This will modify the +// length parameter to the length of pages with the same consecutive access +// rights. The length will start from the first byte of the first page of +// the region. +bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out); + // Allocates a block of memory for a type with the given alignment. // The memory must be freed with AlignedFree. template diff --git a/src/xenia/base/memory_win.cc b/src/xenia/base/memory_win.cc index 27bcfb152..e5d82300d 100644 --- a/src/xenia/base/memory_win.cc +++ b/src/xenia/base/memory_win.cc @@ -50,6 +50,27 @@ DWORD ToWin32ProtectFlags(PageAccess access) { } } +PageAccess ToXeniaProtectFlags(DWORD access) { + if (access & PAGE_GUARD) { + // Strip the page guard flag for now... + access &= ~PAGE_GUARD; + } + + switch (access) { + case PAGE_NOACCESS: + return PageAccess::kNoAccess; + case PAGE_READONLY: + return PageAccess::kReadOnly; + case PAGE_READWRITE: + return PageAccess::kReadWrite; + case PAGE_EXECUTE_READWRITE: + return PageAccess::kExecuteReadWrite; + default: + assert_unhandled_case(access); + return PageAccess::kNoAccess; + } +} + void* AllocFixed(void* base_address, size_t length, AllocationType allocation_type, PageAccess access) { DWORD alloc_type = 0; @@ -103,26 +124,27 @@ bool Protect(void* base_address, size_t length, PageAccess access, return false; } if (out_old_access) { - switch (old_protect) { - case PAGE_NOACCESS: - *out_old_access = PageAccess::kNoAccess; - break; - case PAGE_READONLY: - *out_old_access = PageAccess::kReadOnly; - break; - case PAGE_READWRITE: - *out_old_access = PageAccess::kReadWrite; - break; - case PAGE_EXECUTE_READWRITE: - *out_old_access = PageAccess::kExecuteReadWrite; - default: - assert_unhandled_case(access); - break; - } + *out_old_access = ToXeniaProtectFlags(old_protect); } return true; } +bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out) { + access_out = PageAccess::kNoAccess; + + MEMORY_BASIC_INFORMATION info; + ZeroMemory(&info, sizeof(info)); + + SIZE_T result = VirtualQuery(base_address, &info, length); + if (!result) { + return false; + } + + length = info.RegionSize; + access_out = ToXeniaProtectFlags(info.Protect); + return true; +} + FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, PageAccess access, bool commit) { DWORD protect =