maint: Factor handling of `GetModuleFileNameW` (#3785)

Co-authored-by: Klaim <Klaim@users.noreply.github.com>
This commit is contained in:
Julien Jerphanion 2025-01-31 11:15:55 +02:00 committed by GitHub
parent 195112794a
commit f7d1a29774
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 35 additions and 41 deletions

View File

@ -47,29 +47,45 @@ static_assert(std::is_same_v<mamba::DWORD, ::DWORD>);
namespace mamba
{
#ifdef _WIN32
fs::u8path get_hmodule_path(HMODULE hModule)
{
std::wstring buffer(MAX_PATH, '\0');
DWORD new_size = MAX_PATH;
DWORD size = 0;
// There's unfortunately no way to know how much space is needed,
// so we just keep doubling the size of the buffer until the path fits.
while (true)
{
size = GetModuleFileNameW(hModule, buffer.data(), static_cast<DWORD>(buffer.size()));
if (size == 0)
{
throw mamba::mamba_error(
"Could find the filename of the module handle. (GetModuleFileNameW failed)",
mamba_error_code::internal_failure
);
}
if (size < new_size)
{
break;
}
new_size *= 2;
buffer.resize(new_size);
}
buffer.resize(size);
return fs::absolute(buffer);
}
#endif
// Heavily inspired by https://github.com/gpakosz/whereami/
// check their source to add support for other OS
fs::u8path get_self_exe_path()
{
#ifdef _WIN32
std::wstring buffer(MAX_PATH, '\0');
DWORD size = GetModuleFileNameW(NULL, (wchar_t*) buffer.c_str(), (DWORD) buffer.size());
if (size == 0)
{
throw std::runtime_error("Could find location of the micromamba executable!");
}
else if (size == buffer.size())
{
DWORD new_size = size;
do
{
new_size *= 2;
buffer.reserve(new_size);
size = GetModuleFileNameW(NULL, (wchar_t*) buffer.c_str(), (DWORD) buffer.size());
} while (new_size == size);
}
buffer.resize(buffer.find(L'\0'));
return fs::absolute(buffer);
HMODULE hModule = NULL; // references file used to create the calling process
return get_hmodule_path(hModule);
#elif defined(__APPLE__)
uint32_t size = PATH_MAX;
std::vector<char> buffer(size);
@ -107,29 +123,7 @@ namespace mamba
mamba_error_code::internal_failure
);
}
std::wstring buffer(MAX_PATH, '\0');
DWORD new_size = MAX_PATH;
DWORD size = 0;
while (true)
{
size = GetModuleFileNameW(hModule, buffer.data(), static_cast<DWORD>(buffer.size()));
if (size == 0)
{
throw mamba::mamba_error(
"Could find the filename of the libmamba's module handle. (GetModuleFileNameW failed)",
mamba_error_code::internal_failure
);
}
if (size < new_size)
{
break;
}
new_size *= 2;
buffer.resize(new_size);
}
buffer.resize(size);
return fs::absolute(buffer);
return get_hmodule_path(hModule);
#else
fs::u8path libmamba_path;
Dl_info dl_info;