comparison dep/animone/src/fd/win32.cc @ 342:adb79bdde329

dep/animone: fix tons of issues for example, the window ID stuff was just... completely wrong. since we're supporting multiple different window systems, it *has* to be a union rather than just a single integer type. HWND is also not a DWORD, it's a pointer(!), so now it's stored as a std::uintptr_t. (this probably breaks things)
author Paper <paper@paper.us.eu.org>
date Thu, 20 Jun 2024 03:03:05 -0400
parents 74e2365326c6
children 1faa72660932
comparison
equal deleted inserted replaced
341:052ec053ee37 342:adb79bdde329
10 * even guaranteed to work far into the future. however, just like with macOS, these 10 * even guaranteed to work far into the future. however, just like with macOS, these
11 * things have stayed the same since Vista so if Microsoft *really* wants compatibility 11 * things have stayed the same since Vista so if Microsoft *really* wants compatibility
12 * then they're pretty much forced to keeping this the same anyway. 12 * then they're pretty much forced to keeping this the same anyway.
13 */ 13 */
14 #include "animone/fd/win32.h" 14 #include "animone/fd/win32.h"
15 #include "animone/util.h"
15 #include "animone.h" 16 #include "animone.h"
16 #include "animone/util/win32.h" 17 #include "animone/util/win32.h"
17 18
18 #include <stdexcept> 19 #include <stdexcept>
19 #include <string> 20 #include <string>
20 #include <unordered_map> 21 #include <unordered_map>
21 #include <vector> 22 #include <vector>
23 #include <optional>
22 24
23 #include <fileapi.h> 25 #include <fileapi.h>
24 #include <handleapi.h> 26 #include <handleapi.h>
25 #include <libloaderapi.h> 27 #include <libloaderapi.h>
26 #include <ntdef.h> 28 #include <ntdef.h>
139 } 141 }
140 142
141 /* ------------------------------------------------------------------- */ 143 /* ------------------------------------------------------------------- */
142 144
143 static bool GetSystemDirectory(std::wstring& str) { 145 static bool GetSystemDirectory(std::wstring& str) {
144 PWSTR path_wch; 146 str.assign(MAX_PATH, '\0');
145 147
146 if (FAILED(::SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, SHGFP_TYPE_CURRENT, &path_wch))) 148 return SUCCEEDED(::SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, SHGFP_TYPE_CURRENT, &str.front()));
147 return false;
148
149 str.assign(path_wch);
150
151 ::CoTaskMemFree(path_wch);
152 return true;
153 }
154
155 static bool IsSystemDirectory(const std::string& path) {
156 return IsSystemDirectory(ToWstring(path));
157 } 149 }
158 150
159 static bool IsSystemDirectory(std::wstring path) { 151 static bool IsSystemDirectory(std::wstring path) {
160 std::wstring windir; 152 std::wstring windir;
161 if (!GetSystemDirectory(windir)) 153 if (!GetSystemDirectory(windir))
164 ::CharUpperBuffW(&path.front(), path.length()); 156 ::CharUpperBuffW(&path.front(), path.length());
165 ::CharUpperBuffW(&windir.front(), windir.length()); 157 ::CharUpperBuffW(&windir.front(), windir.length());
166 158
167 // XXX wtf is 4? 159 // XXX wtf is 4?
168 return path.find(windir) == 4; 160 return path.find(windir) == 4;
161 }
162
163 static bool IsSystemDirectory(const std::string& path) {
164 return IsSystemDirectory(ToWstring(path));
169 } 165 }
170 166
171 static bool IsFileHandle(HANDLE handle, unsigned short object_type_index) { 167 static bool IsFileHandle(HANDLE handle, unsigned short object_type_index) {
172 /* this is filled in at runtime because it's not guaranteed to be (and isn't) 168 /* this is filled in at runtime because it's not guaranteed to be (and isn't)
173 * constant between different versions of Windows */ 169 * constant between different versions of Windows */
177 return object_type_index == file_type_index.value(); 173 return object_type_index == file_type_index.value();
178 } else if (!handle) { 174 } else if (!handle) {
179 /* XXX what? */ 175 /* XXX what? */
180 return true; 176 return true;
181 } else if (GetHandleType(handle) == L"File") { 177 } else if (GetHandleType(handle) == L"File") {
182 file_type_index.reset(object_type_index); 178 file_type_index = object_type_index;
183 return true; 179 return true;
184 } 180 }
185 181
186 return false; 182 return false;
187 } 183 }
210 return true; 206 return true;
211 } 207 }
212 208
213 /* ------------------------------------------------------------------- */ 209 /* ------------------------------------------------------------------- */
214 210
215 static std::string GetProcessPath(DWORD process_id) { 211 static bool GetProcessPath(DWORD process_id, std::string& path) {
216 // If we try to open a SYSTEM process, this function fails and the last error 212 // If we try to open a SYSTEM process, this function fails and the last error
217 // code is ERROR_ACCESS_DENIED. 213 // code is ERROR_ACCESS_DENIED.
218 // 214 //
219 // Note that if we requested PROCESS_QUERY_INFORMATION access right instead 215 // Note that if we requested PROCESS_QUERY_INFORMATION access right instead
220 // of PROCESS_QUERY_LIMITED_INFORMATION, this function would fail when used 216 // of PROCESS_QUERY_LIMITED_INFORMATION, this function would fail when used
221 // to open an elevated process. 217 // to open an elevated process.
222 Handle process_handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id)); 218 Handle process_handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id));
223 219
224 if (!process_handle) 220 if (!process_handle)
225 return std::wstring(); 221 return false;
226 222
227 std::wstring buffer(MAX_PATH, L'\0'); 223 std::wstring buffer(MAX_PATH, L'\0');
228 DWORD buf_size = buffer.length(); 224 DWORD buf_size = buffer.length();
229 225
230 // Note that this function requires Windows Vista or above. You may use 226 // Note that this function requires Windows Vista or above. You may use
231 // GetProcessImageFileName or GetModuleFileNameEx on earlier versions. 227 // GetProcessImageFileName or GetModuleFileNameEx on earlier versions.
232 if (!::QueryFullProcessImageNameW(process_handle.get(), 0, &buffer.front(), &buf_size)) 228 if (!::QueryFullProcessImageNameW(process_handle.get(), 0, &buffer.front(), &buf_size))
233 return std::wstring(); 229 return false;
234 230
235 buffer.resize(buf_size); 231 buffer.resize(buf_size);
236 return ToUtf8String(buffer); 232 path = ToUtf8String(buffer);
233 return true;
237 } 234 }
238 235
239 static std::string GetFilenameFromPath(const std::string& path) { 236 static std::string GetFilenameFromPath(const std::string& path) {
240 const auto pos = path.find_last_of(L"/\\"); 237 const auto pos = path.find_last_of("/\\");
241 return pos != std::wstring::npos ? path.substr(pos + 1) : path; 238 return pos != std::wstring::npos ? path.substr(pos + 1) : path;
242 } 239 }
243 240
244 static bool VerifyProcessPath(const std::string& path) { 241 static bool VerifyProcessPath(const std::string& path) {
245 return !path.empty() && !IsSystemDirectory(path); 242 return !path.empty() && !IsSystemDirectory(path);
268 265
269 /* ------------------------------------------------------------------- */ 266 /* ------------------------------------------------------------------- */
270 /* extern functions */ 267 /* extern functions */
271 268
272 bool GetProcessName(pid_t pid, std::string& name) { 269 bool GetProcessName(pid_t pid, std::string& name) {
273 std::string path = GetProcessPath(pid); 270 if (!GetProcessPath(pid, name) || !VerifyProcessPath(name))
274 if (path.empty() || !VerifyProcessPath(path)) 271 return false;
275 return false; 272
276 273 name = GetFilenameFromPath(name);
277 name = GetFilenameFromPath(path);
278 if (!VerifyProcessFilename(name)) 274 if (!VerifyProcessFilename(name))
279 return false; 275 return false;
280 276
281 return true; 277 return true;
282 } 278 }
295 do { 291 do {
296 std::string name; 292 std::string name;
297 if (!GetProcessName(pe32.th32ProcessID, name)) 293 if (!GetProcessName(pe32.th32ProcessID, name))
298 continue; 294 continue;
299 295
300 if (!process_proc({.platform = ExecutablePlatform::Win32, .pid = pe32.th32ProcessID, .comm = name})) 296 if (!process_proc({.pid = pe32.th32ProcessID, .platform = ExecutablePlatform::Win32, .comm = name}))
301 return false; 297 return false;
302 } while (::Process32Next(process_snap.get(), &pe32)); 298 } while (::Process32Next(process_snap.get(), &pe32));
303 299
304 return true; 300 return true;
305 } 301 }