/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2015 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/base/memory.h" #include "xenia/base/platform_win.h" namespace xe { namespace memory { size_t page_size() { static size_t value = 0; if (!value) { SYSTEM_INFO si; GetSystemInfo(&si); value = si.dwPageSize; } return value; } size_t allocation_granularity() { static size_t value = 0; if (!value) { SYSTEM_INFO si; GetSystemInfo(&si); value = si.dwAllocationGranularity; } return value; } DWORD ToWin32ProtectFlags(PageAccess access) { switch (access) { case PageAccess::kNoAccess: return PAGE_NOACCESS; case PageAccess::kReadOnly: return PAGE_READONLY; case PageAccess::kReadWrite: return PAGE_READWRITE; case PageAccess::kExecuteReadWrite: return PAGE_EXECUTE_READWRITE; default: assert_unhandled_case(access); return PAGE_NOACCESS; } } void* AllocFixed(void* base_address, size_t length, AllocationType allocation_type, PageAccess access) { DWORD alloc_type = 0; switch (allocation_type) { case AllocationType::kReserve: alloc_type = MEM_RESERVE; break; case AllocationType::kCommit: alloc_type = MEM_COMMIT; break; case AllocationType::kReserveCommit: alloc_type = MEM_RESERVE | MEM_COMMIT; break; default: assert_unhandled_case(allocation_type); break; } DWORD protect = ToWin32ProtectFlags(access); return VirtualAlloc(base_address, length, alloc_type, protect); } bool DeallocFixed(void* base_address, size_t length, DeallocationType deallocation_type) { DWORD free_type = 0; switch (deallocation_type) { case DeallocationType::kRelease: free_type = MEM_RELEASE; break; case DeallocationType::kDecommit: free_type = MEM_DECOMMIT; break; case DeallocationType::kDecommitRelease: free_type = MEM_RELEASE | MEM_DECOMMIT; break; default: assert_unhandled_case(deallocation_type); break; } return VirtualFree(base_address, length, free_type) ? true : false; } bool Protect(void* base_address, size_t length, PageAccess access, PageAccess* out_old_access) { if (out_old_access) { *out_old_access = PageAccess::kNoAccess; } DWORD new_protect = ToWin32ProtectFlags(access); DWORD old_protect = 0; BOOL result = VirtualProtect(base_address, length, new_protect, &old_protect); if (!result) { 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; } } return true; } FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length, PageAccess access, bool commit) { DWORD protect = ToWin32ProtectFlags(access) | (commit ? SEC_COMMIT : SEC_RESERVE); return CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, protect, static_cast(length >> 32), static_cast(length), path.c_str()); } void CloseFileMappingHandle(FileMappingHandle handle) { CloseHandle(handle); } void* MapFileView(FileMappingHandle handle, void* base_address, size_t length, PageAccess access, size_t file_offset) { DWORD target_address_low = static_cast(file_offset); DWORD target_address_high = static_cast(file_offset >> 32); DWORD file_access = 0; switch (access) { case PageAccess::kReadOnly: file_access = FILE_MAP_READ; break; case PageAccess::kReadWrite: file_access = FILE_MAP_ALL_ACCESS; break; case PageAccess::kExecuteReadWrite: file_access = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE; break; case PageAccess::kNoAccess: default: assert_unhandled_case(access); return nullptr; } return MapViewOfFileEx(handle, file_access, target_address_high, target_address_low, length, base_address); } bool UnmapFileView(FileMappingHandle handle, void* base_address, size_t length) { return UnmapViewOfFile(base_address) ? true : false; } } // namespace memory } // namespace xe