Skip to content
Permalink
Browse files
Merge pull request #10452 from AdmiralCurtiss/win7-unmap-view-of-file-ex
MemArena: Restore Windows 7 support.
  • Loading branch information
JosJuice committed Feb 14, 2022
2 parents 7c91acb + 4a9553b commit eba1998
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 15 deletions.
@@ -7,6 +7,7 @@
#include <vector>

#include "Common/CommonTypes.h"
#include "Common/DynamicLibrary.h"

namespace Common
{
@@ -106,7 +107,9 @@ class MemArena final
std::vector<WindowsMemoryRegion> m_regions;
void* m_reserved_region = nullptr;
void* m_memory_handle = nullptr;
void* m_api_ms_win_core_memory_l1_1_6_handle = nullptr;
Common::DynamicLibrary m_kernel32_handle;
Common::DynamicLibrary m_api_ms_win_core_memory_l1_1_6_handle;
void* m_address_UnmapViewOfFileEx = nullptr;
void* m_address_VirtualAlloc2 = nullptr;
void* m_address_MapViewOfFile3 = nullptr;
#else
@@ -29,6 +29,8 @@ using PMapViewOfFile3 = PVOID(WINAPI*)(HANDLE FileMapping, HANDLE Process, PVOID
MEM_EXTENDED_PARAMETER* ExtendedParameters,
ULONG ParameterCount);

using PUnmapViewOfFileEx = BOOL(WINAPI*)(PVOID BaseAddress, ULONG UnmapFlags);

using PIsApiSetImplemented = BOOL(APIENTRY*)(PCSTR Contract);

namespace Common
@@ -61,31 +63,38 @@ MemArena::MemArena()
if (!static_cast<PIsApiSetImplemented>(ptr_IsApiSetImplemented)("api-ms-win-core-memory-l1-1-6"))
return;

const HMODULE handle = LoadLibraryW(L"api-ms-win-core-memory-l1-1-6.dll");
if (!handle)
m_api_ms_win_core_memory_l1_1_6_handle.Open("api-ms-win-core-memory-l1-1-6.dll");
m_kernel32_handle.Open("Kernel32.dll");
if (!m_api_ms_win_core_memory_l1_1_6_handle.IsOpen() || !m_kernel32_handle.IsOpen())
{
m_api_ms_win_core_memory_l1_1_6_handle.Close();
m_kernel32_handle.Close();
return;
}

void* const address_VirtualAlloc2 = GetProcAddress(handle, "VirtualAlloc2FromApp");
void* const address_MapViewOfFile3 = GetProcAddress(handle, "MapViewOfFile3FromApp");
if (address_VirtualAlloc2 && address_MapViewOfFile3)
void* const address_VirtualAlloc2 =
m_api_ms_win_core_memory_l1_1_6_handle.GetSymbolAddress("VirtualAlloc2FromApp");
void* const address_MapViewOfFile3 =
m_api_ms_win_core_memory_l1_1_6_handle.GetSymbolAddress("MapViewOfFile3FromApp");
void* const address_UnmapViewOfFileEx = m_kernel32_handle.GetSymbolAddress("UnmapViewOfFileEx");
if (address_VirtualAlloc2 && address_MapViewOfFile3 && address_UnmapViewOfFileEx)
{
m_api_ms_win_core_memory_l1_1_6_handle = handle;
m_address_VirtualAlloc2 = address_VirtualAlloc2;
m_address_MapViewOfFile3 = address_MapViewOfFile3;
m_address_UnmapViewOfFileEx = address_UnmapViewOfFileEx;
}
else
{
// at least one function is not available, use legacy logic
FreeLibrary(handle);
m_api_ms_win_core_memory_l1_1_6_handle.Close();
m_kernel32_handle.Close();
}
}

MemArena::~MemArena()
{
ReleaseMemoryRegion();
ReleaseSHMSegment();
if (m_api_ms_win_core_memory_l1_1_6_handle)
FreeLibrary(static_cast<HMODULE>(m_api_ms_win_core_memory_l1_1_6_handle));
}

void MemArena::GrabSHMSegment(size_t size)
@@ -123,7 +132,7 @@ u8* MemArena::ReserveMemoryRegion(size_t memory_size)
}

u8* base;
if (m_api_ms_win_core_memory_l1_1_6_handle)
if (m_api_ms_win_core_memory_l1_1_6_handle.IsOpen())
{
base = static_cast<u8*>(static_cast<PVirtualAlloc2>(m_address_VirtualAlloc2)(
nullptr, nullptr, memory_size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS,
@@ -154,7 +163,7 @@ u8* MemArena::ReserveMemoryRegion(size_t memory_size)

void MemArena::ReleaseMemoryRegion()
{
if (m_api_ms_win_core_memory_l1_1_6_handle && m_reserved_region)
if (m_api_ms_win_core_memory_l1_1_6_handle.IsOpen() && m_reserved_region)
{
// user should have unmapped everything by this point, check if that's true and yell if not
// (it indicates a bug in the emulated memory mapping logic)
@@ -291,7 +300,7 @@ WindowsMemoryRegion* MemArena::EnsureSplitRegionForMapping(void* start_address,

void* MemArena::MapInMemoryRegion(s64 offset, size_t size, void* base)
{
if (m_api_ms_win_core_memory_l1_1_6_handle)
if (m_api_ms_win_core_memory_l1_1_6_handle.IsOpen())
{
WindowsMemoryRegion* const region = EnsureSplitRegionForMapping(base, size);
if (!region)
@@ -393,9 +402,10 @@ bool MemArena::JoinRegionsAfterUnmap(void* start_address, size_t size)

void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
{
if (m_api_ms_win_core_memory_l1_1_6_handle)
if (m_api_ms_win_core_memory_l1_1_6_handle.IsOpen())
{
if (UnmapViewOfFileEx(view, MEM_PRESERVE_PLACEHOLDER))
if (static_cast<PUnmapViewOfFileEx>(m_address_UnmapViewOfFileEx)(view,
MEM_PRESERVE_PLACEHOLDER))
{
if (!JoinRegionsAfterUnmap(view, size))
PanicAlertFmt("Joining memory region failed.");

0 comments on commit eba1998

Please sign in to comment.