// Resolve artifacts that ship in the deployable bin// root even when the // running executable lives in a sibling subfolder (e.g. dev tools staged under // bin//tools/). The probes use this to find coop_hook.dll and the x86 // injector helper, which stay at the root while the probes themselves do not. #pragma once #include #include #include namespace coop { // Directory of the current executable, with a trailing separator. inline std::wstring exe_directory() { wchar_t buf[MAX_PATH] = {}; GetModuleFileNameW(nullptr, buf, MAX_PATH); std::wstring path(buf); const std::size_t slash = path.find_last_of(L"\\/"); return slash == std::wstring::npos ? std::wstring() : path.substr(0, slash + 1); } // Full path to a deployed artifact `name`: prefer one next to the running exe, else // one directory up (the deployable root, when the exe runs from a tools/ subfolder). // Falls back to the next-to-exe path so callers can report a sensible "not found". inline std::wstring deployed_artifact_path(const wchar_t* name) { const std::wstring here = exe_directory() + name; if (GetFileAttributesW(here.c_str()) != INVALID_FILE_ATTRIBUTES) { return here; } std::wstring dir = exe_directory(); if (!dir.empty()) { dir.pop_back(); // drop the trailing separator before going up a level } const std::size_t slash = dir.find_last_of(L"\\/"); if (slash != std::wstring::npos) { const std::wstring up = dir.substr(0, slash + 1) + name; if (GetFileAttributesW(up.c_str()) != INVALID_FILE_ATTRIBUTES) { return up; } } return here; } } // namespace coop