Mercurial > minori
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 } |
