annotate src/util/win32.cc @ 19:6596be6917a1

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