Skip to content

Instantly share code, notes, and snippets.

@ArunTS96
Last active May 1, 2020 15:43
Show Gist options
  • Save ArunTS96/c6bf7d00b8623ebf79776055cf90e775 to your computer and use it in GitHub Desktop.
Save ArunTS96/c6bf7d00b8623ebf79776055cf90e775 to your computer and use it in GitHub Desktop.
Where.exe source code. This will return full path to file from filename by checking through system directory, windows directory and path variable. Windows.
std::wstring ProcessHandleToNameW(const HANDLE process)
{
DWORD buffSize = page_size;
std::wstring ret(page_size, 0);
if (!QueryFullProcessImageNameW(process, 0, &ret[0], &buffSize))
{
STANDARD_GET_LAST_ERROR("QueryFullProcessImageNameW");
ret.clear();
}
else
{
ret.resize(buffSize); //here only buffsize. not buffsize-1
USERMSG("%ws is the path\n", ret.c_str());
}
return ret;
}
std::filesystem::path ProcessHandleToPath(const HANDLE process)
{
return std::filesystem::path(ProcessHandleToNameW(process));
}
std::filesystem::path GetCurrentProcessImagePath()
{
static auto currentModulePath = ProcessHandleToPath(GetCurrentProcess());
return currentModulePath;
}
std::map<std::wstring, std::wstring> GetEnvAsMap()
{
std::map<std::wstring, std::basic_string<wchar_t>> env;
auto free = [](wchar_t* p) { FreeEnvironmentStringsW(p); };
const auto envBlock = std::unique_ptr<wchar_t, decltype(free)>{
GetEnvironmentStringsW(), free };
for (auto i = envBlock.get(); *i != L'\0'; ++i) {
std::wstring key;
std::wstring value;
for (; *i != L'='; ++i)
key += *i;
++i;
for (; *i != L'\0'; ++i)
value += *i;
env[key] = value;
}
return env;
}
template <class Char, typename Out>
void Split(const std::basic_string<Char>& s, Char delim, Out result) {
std::basic_istringstream<Char, std::char_traits<Char>, std::allocator<Char>> iss(s);
std::basic_string<Char> item;
while (std::getline(iss, item, delim)) {
*result++ = item;
}
}
template <class Char>
std::vector<std::basic_string<Char>> Split(const std::basic_string<Char>& s, Char delim)
{
std::vector<std::basic_string<Char>> elems;
Split<Char>(s, delim, std::back_inserter(elems));
return elems;
}
template <class Char>
class Where
{
std::vector<std::filesystem::path> paths_;
Where()
{
paths_.emplace_back(GetCurrentProcessImagePath());
wchar_t curDir[page_size];
if (GetCurrentDirectoryW(page_size, curDir))
paths_.emplace_back(curDir);
auto getDirAndEmplace = [&](const decltype(GetSystemDirectoryW) getter)
{
wchar_t dir[page_size];
if (getter(dir, page_size))
paths_.emplace_back(dir);
};
getDirAndEmplace(GetSystemDirectoryW);
getDirAndEmplace(GetWindowsDirectoryW);
for (auto& i : Split<Char>(GetEnvAsMap()[L"Path"], L';'))
{
if (i.back() == L'\\')
{
std::filesystem::path p = i;
paths_.emplace_back(i);
}
else
{
paths_.emplace_back(i + L'\\');
}
}
}
~Where() = default;
public:
static Where& GetInstance()
{
static Where instance;
return instance;
}
std::optional<std::filesystem::path> GetFullyFormedPath(const std::basic_string<Char>& file)
{
std::filesystem::path fileName(file);
if (!fileName.has_extension())
fileName = fileName.native() + L".exe";
for(auto &i : paths_)
{
std::filesystem::path fullPath(i.native() + fileName.native());
if (exists(fullPath))
return fullPath;
}
return {};
}
Where& operator=(const Where&) = delete;
Where(const Where&) = delete;
Where(Where&&) = delete;
Where& operator=(Where&&) = delete;
};
int main()
{
auto wh = &(Where<wchar_t>::GetInstance());
auto path = wh->GetFullyFormedPath(L"ping");
if (path.has_value())
std::wcout << *path << L"\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment