diff --git a/Source/Core/Common/MemArena.h b/Source/Core/Common/MemArena.h index bdde5579c5..7a0a683579 100644 --- a/Source/Core/Common/MemArena.h +++ b/Source/Core/Common/MemArena.h @@ -7,6 +7,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/DynamicLibrary.h" namespace Common { @@ -106,7 +107,9 @@ private: std::vector 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 diff --git a/Source/Core/Common/MemArenaWin.cpp b/Source/Core/Common/MemArenaWin.cpp index 6434627478..1e2de701c5 100644 --- a/Source/Core/Common/MemArenaWin.cpp +++ b/Source/Core/Common/MemArenaWin.cpp @@ -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,22 +63,31 @@ MemArena::MemArena() if (!static_cast(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) - return; - - void* const address_VirtualAlloc2 = GetProcAddress(handle, "VirtualAlloc2FromApp"); - void* const address_MapViewOfFile3 = GetProcAddress(handle, "MapViewOfFile3FromApp"); - if (address_VirtualAlloc2 && address_MapViewOfFile3) + 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 = + 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(); } } @@ -84,8 +95,6 @@ MemArena::~MemArena() { ReleaseMemoryRegion(); ReleaseSHMSegment(); - if (m_api_ms_win_core_memory_l1_1_6_handle) - FreeLibrary(static_cast(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(static_cast(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(m_address_UnmapViewOfFileEx)(view, + MEM_PRESERVE_PLACEHOLDER)) { if (!JoinRegionsAfterUnmap(view, size)) PanicAlertFmt("Joining memory region failed.");