Hello
I've seen a lot of people having trouble running some maple versions on Windows 11.
The affected versions I've seen seem to be 32bit versions above v176, but more versions could be affected.
I ran into the same problem when trying to run v207.
The Problem
Some time after launching the game, I get the following error:
It took some research, but what seems to happen is that maple is copying DLLs into a temp path and then loads them from there.
The code that does that is virtualized so I didn't bother trying to understand it.
What seems to happen is that in some cases, the game tries to load the copied DLL before the copying process finishes (how do you even code something this garbage?? wth nexon).
The Fix
If maple is copying the DLLs and then loading them, lets just make it load the original DLL.
1. The first step is to keep track of files that are being copied:
(Don't mind the crappy BasepCopyFileExW signature and jmp to the original function, I can't seem to get the function signature right
2. The second step is to make every try of loading a copied DLL load the original one:
Hope this helps someone
I've seen a lot of people having trouble running some maple versions on Windows 11.
The affected versions I've seen seem to be 32bit versions above v176, but more versions could be affected.
I ran into the same problem when trying to run v207.
The Problem
Some time after launching the game, I get the following error:
It took some research, but what seems to happen is that maple is copying DLLs into a temp path and then loads them from there.
The code that does that is virtualized so I didn't bother trying to understand it.
What seems to happen is that in some cases, the game tries to load the copied DLL before the copying process finishes (how do you even code something this garbage?? wth nexon).
The Fix
If maple is copying the DLLs and then loading them, lets just make it load the original DLL.
1. The first step is to keep track of files that are being copied:
PHP:
std::mutex coped_files_mutex;
std::unordered_map<std::wstring, std::wstring> copied_files;
WINBASEAPI
BOOL
WINAPI
BasepCopyFileExW(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
...
);
void BasepCopyFileExW_hook_impl(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
{
if ((nullptr != lpExistingFileName) && (nullptr != lpNewFileName))
{
std::unique_lock copied_dlls_lock(coped_files_mutex);
copied_files[lpNewFileName] = lpExistingFileName;
}
}
__declspec(naked)
BOOL
WINAPI
BasepCopyFileExW_hook(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
...
)
{
BasepCopyFileExW_hook_impl(lpExistingFileName, lpNewFileName);
__asm {
jmp original_BasepCopyFileExW
}
}
(Don't mind the crappy BasepCopyFileExW signature and jmp to the original function, I can't seem to get the function signature right
2. The second step is to make every try of loading a copied DLL load the original one:
PHP:
NTSTATUS
NTAPI
LdrLoadDll_hook(
PWSTR search_path OPTIONAL, PULONG dll_characteristics OPTIONAL, PUNICODE_STRING dll_name,
PVOID* base_address
)
{
if ((nullptr != dll_name) && (nullptr != dll_name->Buffer))
{
auto* begin = dll_name->Buffer;
auto* end = reinterpret_cast<PWSTR>(reinterpret_cast<PBYTE>(begin) + dll_name->Length);
std::wstring dll_path(begin, end);
std::wstring original_dll;
{
std::unique_lock copied_dlls_lock(coped_files_mutex);
original_dll = copied_files[dll_path];
}
if (!original_dll.empty())
{
*base_address = LoadLibraryW(original_dll.c_str());
return STATUS_SUCCESS;
}
}
return original_LdrLoadDll(search_path, dll_characteristics, dll_name, base_address);
}
Hope this helps someone
Last edited: