258
+ − 1 #include "animone/util/win32.h"
+ − 2
+ − 3 #include <shlobj.h> /* SHGetKnownFolderPath */
+ − 4 #include <subauth.h> /* UNICODE_STRING */
+ − 5 #include <windows.h>
+ − 6
+ − 7 namespace animone::internal::win32 {
+ − 8
+ − 9 std::string ToUtf8String(const std::wstring& string) {
+ − 10 if (string.empty())
+ − 11 return std::string();
+ − 12
+ − 13 long size = ::WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), nullptr, 0, nullptr, nullptr);
+ − 14 std::string ret(size, '\0');
+ − 15 ::WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), &ret.front(), ret.length(), nullptr, nullptr);
+ − 16 return ret;
+ − 17 }
+ − 18
+ − 19 std::string ToUtf8String(const UNICODE_STRING& string) {
+ − 20 const auto wctomb = [&string](LPSTR out, int size) -> int {
+ − 21 return ::WideCharToMultiByte(CP_UTF8, 0, string.Buffer, string.Length, out, size, nullptr, nullptr);
+ − 22 };
+ − 23
+ − 24 if (string.Length <= 0)
+ − 25 return std::string();
+ − 26
+ − 27 long size = wctomb(nullptr, 0);
+ − 28 std::string ret(size, '\0');
+ − 29 wctomb(&ret.front(), ret.length());
+ − 30 return ret;
+ − 31 }
+ − 32
+ − 33 std::wstring ToWstring(const std::string& string) {
+ − 34 const auto mbtowc = [&string](LPWSTR out, int size) -> int {
+ − 35 return ::MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.length(), out, size);
+ − 36 };
+ − 37
+ − 38 if (string.empty())
+ − 39 return std::wstring();
+ − 40
+ − 41 long size = mbtowc(nullptr, 0);
+ − 42 std::wstring ret(size, L'\0');
+ − 43 mbtowc(&ret.front(), ret.length());
+ − 44 return ret;
+ − 45 }
+ − 46
+ − 47 std::wstring GetProcessPath(DWORD process_id) {
+ − 48 // If we try to open a SYSTEM process, this function fails and the last error
+ − 49 // code is ERROR_ACCESS_DENIED.
+ − 50 //
+ − 51 // Note that if we requested PROCESS_QUERY_INFORMATION access right instead
+ − 52 // of PROCESS_QUERY_LIMITED_INFORMATION, this function would fail when used
+ − 53 // to open an elevated process.
+ − 54 Handle process_handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id));
+ − 55
+ − 56 if (!process_handle)
+ − 57 return std::wstring();
+ − 58
+ − 59 std::wstring buffer(MAX_PATH, L'\0');
+ − 60 DWORD buf_size = buffer.length();
+ − 61
+ − 62 // Note that this function requires Windows Vista or above. You may use
+ − 63 // GetProcessImageFileName or GetModuleFileNameEx on earlier versions.
+ − 64 if (!::QueryFullProcessImageNameW(process_handle.get(), 0, &buffer.front(), &buf_size))
+ − 65 return std::wstring();
+ − 66
+ − 67 buffer.resize(buf_size);
+ − 68 return buffer;
+ − 69 }
+ − 70
+ − 71 std::wstring GetFileNameFromPath(const std::wstring& path) {
+ − 72 const auto pos = path.find_last_of(L"/\\");
+ − 73 return pos != std::wstring::npos ? path.substr(pos + 1) : path;
+ − 74 }
+ − 75
+ − 76 std::wstring GetFileNameWithoutExtension(const std::wstring& filename) {
+ − 77 const auto pos = filename.find_last_of(L".");
+ − 78 return pos != std::wstring::npos ? filename.substr(0, pos) : filename;
+ − 79 }
+ − 80
+ − 81 static std::wstring GetSystemDirectory() {
+ − 82 PWSTR path_wch;
+ − 83 SHGetKnownFolderPath(FOLDERID_Windows, 0, NULL, &path_wch);
+ − 84 std::wstring path_wstr(path_wch);
+ − 85 CoTaskMemFree(path_wch);
+ − 86 return path_wstr;
+ − 87 }
+ − 88
+ − 89 bool IsSystemDirectory(const std::string& path) {
+ − 90 return IsSystemDirectory(ToWstring(path));
+ − 91 }
+ − 92
+ − 93 bool IsSystemDirectory(std::wstring path) {
+ − 94 ::CharUpperBuffW(&path.front(), path.length());
+ − 95
+ − 96 std::wstring windir = GetSystemDirectory();
+ − 97 ::CharUpperBuffW(&windir.front(), windir.length());
+ − 98
+ − 99 return path.find(windir) == 4;
+ − 100 }
+ − 101
+ − 102 } // namespace animone::internal::win32