From 10ddc840c297495a3a6cd38151f73e52dde8a13d Mon Sep 17 00:00:00 2001 From: Julien Jerphanion Date: Thu, 30 Jan 2025 07:57:32 +0100 Subject: [PATCH] maint: Factor handling of `GetModuleFileNameW` Signed-off-by: Julien Jerphanion Co-authored-by: Klaim --- libmamba/src/core/util_os.cpp | 74 ++++++++++++++++------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/libmamba/src/core/util_os.cpp b/libmamba/src/core/util_os.cpp index 4332dacc09..2758372074 100644 --- a/libmamba/src/core/util_os.cpp +++ b/libmamba/src/core/util_os.cpp @@ -47,29 +47,45 @@ static_assert(std::is_same_v); namespace mamba { - // 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 + fs::u8path get_hmodule_path(HMODULE hModule) + { 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 = 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) { - DWORD new_size = size; - do + size = GetModuleFileNameW(hModule, buffer.data(), static_cast(buffer.size())); + if (size == 0) { - new_size *= 2; - buffer.reserve(new_size); - size = GetModuleFileNameW(NULL, (wchar_t*) buffer.c_str(), (DWORD) buffer.size()); - } while (new_size == size); + 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(buffer.find(L'\0')); + 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 + 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 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(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;