hopefully i dont regret doing allat

This commit is contained in:
Mars 2025-04-26 01:20:39 -04:00
parent 39e5a6a509
commit cd74075a2e
9 changed files with 365 additions and 313 deletions

View file

@ -5,12 +5,11 @@
#include <windows.h>
#include <wincrypt.h>
#include <dwmapi.h>
#include <tlhelp32.h>
// clang-format on
#include <cstring>
#include <ranges>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Media.Control.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.System.Diagnostics.h>
@ -60,47 +59,6 @@ namespace {
}};
// clang-format on
class ProcessSnapshot {
public:
ProcessSnapshot() : h_snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) {}
ProcessSnapshot(ProcessSnapshot&&) = delete;
ProcessSnapshot(const ProcessSnapshot&) = delete;
fn operator=(ProcessSnapshot&&)->ProcessSnapshot& = delete;
fn operator=(const ProcessSnapshot&)->ProcessSnapshot& = delete;
~ProcessSnapshot() {
if (h_snapshot != INVALID_HANDLE_VALUE)
CloseHandle(h_snapshot);
}
[[nodiscard]] fn isValid() const -> bool { return h_snapshot != INVALID_HANDLE_VALUE; }
[[nodiscard]] fn getProcesses() const -> Vec<Pair<DWORD, String>> {
Vec<Pair<DWORD, String>> processes;
if (!isValid())
return processes;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(h_snapshot, &pe32))
return processes;
if (Process32First(h_snapshot, &pe32)) {
processes.emplace_back(pe32.th32ProcessID, String(reinterpret_cast<const char*>(pe32.szExeFile)));
while (Process32Next(h_snapshot, &pe32))
processes.emplace_back(pe32.th32ProcessID, String(reinterpret_cast<const char*>(pe32.szExeFile)));
}
return processes;
}
HANDLE h_snapshot;
};
fn GetRegistryValue(const HKEY& hKey, const String& subKey, const String& valueName) -> String {
HKEY key = nullptr;
if (RegOpenKeyExA(hKey, subKey.c_str(), 0, KEY_READ, &key) != ERROR_SUCCESS)
@ -125,88 +83,74 @@ namespace {
return value;
}
fn GetProcessInfo() -> Vec<Pair<DWORD, String>> {
const ProcessSnapshot snapshot;
return snapshot.isValid() ? snapshot.getProcesses() : std::vector<std::pair<DWORD, String>> {};
fn GetProcessInfo() -> Result<Vec<Pair<DWORD, String>>, OsError> {
try {
using namespace winrt::Windows::System::Diagnostics;
using namespace winrt::Windows::Foundation::Collections;
const IVectorView<ProcessDiagnosticInfo> processInfos = ProcessDiagnosticInfo::GetForProcesses();
Vec<Pair<DWORD, String>> processes;
processes.reserve(processInfos.Size());
for (const auto& processInfo : processInfos)
processes.emplace_back(processInfo.ProcessId(), winrt::to_string(processInfo.ExecutableFileName()));
return processes;
} catch (const winrt::hresult_error& e) { return Err(OsError(e)); } catch (const std::exception& e) {
return Err(OsError(e));
}
}
fn IsProcessRunning(const Vec<String>& processes, const String& name) -> bool {
return std::ranges::any_of(processes, [&name](const String& proc) -> bool {
fn IsProcessRunning(const Vec<String>& processNames, const String& name) -> bool {
return std::ranges::any_of(processNames, [&name](const String& proc) -> bool {
return _stricmp(proc.c_str(), name.c_str()) == 0;
});
}
fn GetParentProcessId(const DWORD pid) -> DWORD {
const ProcessSnapshot snapshot;
if (!snapshot.isValid())
return 0;
PROCESSENTRY32 pe32 { .dwSize = sizeof(PROCESSENTRY32) };
if (!Process32First(snapshot.h_snapshot, &pe32))
return 0;
if (pe32.th32ProcessID == pid)
return pe32.th32ParentProcessID;
while (Process32Next(snapshot.h_snapshot, &pe32))
if (pe32.th32ProcessID == pid)
return pe32.th32ParentProcessID;
return 0;
}
fn GetProcessName(const DWORD pid) -> String {
const ProcessSnapshot snapshot;
if (!snapshot.isValid())
return "";
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(snapshot.h_snapshot, &pe32))
return "";
if (pe32.th32ProcessID == pid)
return reinterpret_cast<const char*>(pe32.szExeFile);
while (Process32Next(snapshot.h_snapshot, &pe32))
if (pe32.th32ProcessID == pid)
return reinterpret_cast<const char*>(pe32.szExeFile);
return "";
}
template <usize sz>
fn FindShellInProcessTree(const DWORD startPid, const Array<Pair<StringView, StringView>, sz>& shellMap)
-> std::optional<String> {
DWORD pid = startPid;
while (pid != 0) {
String processName = GetProcessName(pid);
-> Option<String> {
if (startPid == 0)
return None;
if (processName.empty()) {
pid = GetParentProcessId(pid);
continue;
try {
using namespace winrt::Windows::System::Diagnostics;
ProcessDiagnosticInfo currentProcessInfo = nullptr;
try {
currentProcessInfo = ProcessDiagnosticInfo::TryGetForProcessId(startPid);
} catch (const winrt::hresult_error& e) {
RETURN_ERR("Failed to get process info for PID {}: {}", startPid, winrt::to_string(e.message()));
}
std::ranges::transform(processName, processName.begin(), [](const u8 character) {
return static_cast<char>(std::tolower(static_cast<unsigned char>(character)));
});
while (currentProcessInfo) {
String processName = winrt::to_string(currentProcessInfo.ExecutableFileName());
if (processName.length() > 4 && processName.substr(processName.length() - 4) == ".exe")
processName.resize(processName.length() - 4);
if (!processName.empty()) {
std::ranges::transform(processName, processName.begin(), [](const u8 character) {
return static_cast<char>(std::tolower(static_cast<unsigned char>(character)));
});
auto iter = std::ranges::find_if(shellMap, [&](const auto& pair) {
return std::string_view { processName } == pair.first;
});
if (processName.length() > 4 && processName.ends_with(".exe"))
processName.resize(processName.length() - 4);
if (iter != std::ranges::end(shellMap))
return String { iter->second };
auto iter =
std::ranges::find_if(shellMap, [&](const auto& pair) { return StringView { processName } == pair.first; });
pid = GetParentProcessId(pid);
if (iter != std::ranges::end(shellMap))
return String { iter->second };
}
currentProcessInfo = currentProcessInfo.Parent();
}
} catch (const winrt::hresult_error& e) {
ERROR_LOG("WinRT error during process tree walk (start PID {}): {}", startPid, winrt::to_string(e.message()));
} catch (const std::exception& e) {
ERROR_LOG("Standard exception during process tree walk (start PID {}): {}", startPid, e.what());
}
return std::nullopt;
return None;
}
fn GetBuildNumber() -> Option<u64> {
@ -227,36 +171,40 @@ namespace {
}
}
fn os::GetMemInfo() -> Result<u64, String> {
fn os::GetMemInfo() -> Result<u64, OsError> {
try {
return winrt::Windows::System::Diagnostics::SystemDiagnosticInfo::GetForCurrentSystem()
.MemoryUsage()
.GetReport()
.TotalPhysicalSizeInBytes();
} catch (const winrt::hresult_error& e) {
return Err(std::format("Failed to get memory info: {}", to_string(e.message())));
}
} catch (const winrt::hresult_error& e) { return Err(OsError(e)); }
}
fn os::GetNowPlaying() -> Result<String, NowPlayingError> {
fn os::GetNowPlaying() -> Result<MediaInfo, NowPlayingError> {
using namespace winrt::Windows::Media::Control;
using namespace winrt::Windows::Foundation;
using Session = GlobalSystemMediaTransportControlsSession;
using SessionManager = GlobalSystemMediaTransportControlsSessionManager;
using Session = GlobalSystemMediaTransportControlsSession;
using SessionManager = GlobalSystemMediaTransportControlsSessionManager;
using MediaProperties = GlobalSystemMediaTransportControlsSessionMediaProperties;
try {
const IAsyncOperation<SessionManager> sessionManagerOp = SessionManager::RequestAsync();
const SessionManager sessionManager = sessionManagerOp.get();
if (const Session currentSession = sessionManager.GetCurrentSession())
return winrt::to_string(currentSession.TryGetMediaPropertiesAsync().get().Title());
if (const Session currentSession = sessionManager.GetCurrentSession()) {
const MediaProperties mediaProperties = currentSession.TryGetMediaPropertiesAsync().get();
return MediaInfo(
winrt::to_string(mediaProperties.Title()), winrt::to_string(mediaProperties.Artist()), None, None
);
}
return Err(NowPlayingCode::NoActivePlayer);
} catch (const winrt::hresult_error& e) { return Err(e); }
} catch (const winrt::hresult_error& e) { return Err(OsError(e)); }
}
fn os::GetOSVersion() -> Result<String, String> {
fn os::GetOSVersion() -> Result<String, OsError> {
try {
const String regSubKey = R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)";
@ -264,26 +212,33 @@ fn os::GetOSVersion() -> Result<String, String> {
const String displayVersion = GetRegistryValue(HKEY_LOCAL_MACHINE, regSubKey, "DisplayVersion");
if (productName.empty())
return Err("Failed to read ProductName");
return Err(OsError { OsErrorCode::NotFound, "ProductName not found in registry" });
if (const Option<u64> buildNumber = GetBuildNumber()) {
if (*buildNumber >= 22000)
if (const usize pos = productName.find("Windows 10");
pos != String::npos && (pos == 0 || !isalnum(static_cast<u8>(productName[pos - 1]))) &&
(pos + 10 == productName.length() || !isalnum(static_cast<u8>(productName[pos + 10]))))
productName.replace(pos, 10, "Windows 11");
} else
DEBUG_LOG("Warning: Could not get build number via WinRT; Win11 patch relies on registry ProductName only.");
if (const Option<u64> buildNumberOpt = GetBuildNumber()) {
if (const u64 buildNumber = *buildNumberOpt; buildNumber >= 22000) {
if (const size_t pos = productName.find("Windows 10"); pos != String::npos) {
const bool startBoundary = (pos == 0 || !isalnum(static_cast<unsigned char>(productName[pos - 1])));
const bool endBoundary =
(pos + 10 == productName.length() || !isalnum(static_cast<unsigned char>(productName[pos + 10])));
if (startBoundary && endBoundary) {
productName.replace(pos, 10, "Windows 11");
}
}
}
} else {
DEBUG_LOG("Warning: Could not get build number via WinRT; Win11 detection might be inaccurate.");
}
return displayVersion.empty() ? productName : productName + " " + displayVersion;
} catch (const Exception& e) { return Err(std::format("Exception occurred getting OS version: {}", e.what())); }
} catch (const std::exception& e) { return Err(OsError(e)); }
}
fn os::GetHost() -> String {
fn os::GetHost() -> Result<String, OsError> {
return GetRegistryValue(HKEY_LOCAL_MACHINE, R"(SYSTEM\HardwareConfig\Current)", "SystemFamily");
}
fn os::GetKernelVersion() -> String {
fn os::GetKernelVersion() -> Result<String, OsError> {
try {
using namespace winrt::Windows::System::Profile;
@ -292,36 +247,47 @@ fn os::GetKernelVersion() -> String {
if (const winrt::hstring familyVersion = versionInfo.DeviceFamilyVersion(); !familyVersion.empty())
if (auto [major, minor, build, revision] = OSVersion::parseDeviceFamilyVersion(familyVersion); build > 0)
return std::format("{}.{}.{}.{}", major, minor, build, revision);
} catch (const winrt::hresult_error& e) {
ERROR_LOG("WinRT error: {}", winrt::to_string(e.message()));
} catch (const Exception& e) { ERROR_LOG("Failed to get kernel version: {}", e.what()); }
} catch (const winrt::hresult_error& e) { return Err(OsError(e)); } catch (const Exception& e) {
return Err(OsError(e));
}
return "";
return Err(OsError { OsErrorCode::NotFound, "Could not determine kernel version" });
}
fn os::GetWindowManager() -> String {
const auto processInfo = GetProcessInfo();
std::vector<String> processNames;
fn os::GetWindowManager() -> Option<String> {
if (const Result<Vec<Pair<DWORD, String>>, OsError> processInfoResult = GetProcessInfo()) {
const Vec<Pair<DWORD, String>>& processInfo = *processInfoResult;
processNames.reserve(processInfo.size());
for (const auto& name : processInfo | std::views::values) processNames.push_back(name);
Vec<String> processNames;
processNames.reserve(processInfo.size());
const std::unordered_map<String, String> wmProcesses = {
{ "glazewm.exe", "GlazeWM" },
{ "fancywm.exe", "FancyWM" },
{ "komorebi.exe", "Komorebi" },
{ "komorebic.exe", "Komorebi" }
};
for (const String& val : processInfo | std::views::values) {
if (!val.empty()) {
const usize lastSlash = val.find_last_of("/\\");
processNames.push_back(lastSlash == String::npos ? val : val.substr(lastSlash + 1));
}
}
for (const auto& [processName, wmName] : wmProcesses)
if (IsProcessRunning(processNames, processName))
return wmName;
const std::unordered_map<String, String> wmProcesses = {
{ "glazewm.exe", "GlazeWM" },
{ "fancywm.exe", "FancyWM" },
{ "komorebi.exe", "Komorebi" },
{ "komorebic.exe", "Komorebi" },
};
for (const auto& [processExe, wmName] : wmProcesses)
if (IsProcessRunning(processNames, processExe))
return wmName;
} else {
ERROR_LOG("Failed to get process info for WM detection: {}", processInfoResult.error().message);
}
BOOL compositionEnabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&compositionEnabled)))
return compositionEnabled ? "DWM" : "Windows Manager (Basic)";
return "Windows Manager";
return None;
}
fn os::GetDesktopEnvironment() -> Option<String> {
@ -371,51 +337,60 @@ fn os::GetDesktopEnvironment() -> Option<String> {
}
}
fn os::GetShell() -> String {
const DWORD currentPid = GetCurrentProcessId();
fn os::GetShell() -> Option<String> {
try {
const DWORD currentPid =
winrt::Windows::System::Diagnostics::ProcessDiagnosticInfo::GetForCurrentProcess().ProcessId();
if (const Result<String, EnvError> msystemResult = GetEnv("MSYSTEM")) {
String shellPath;
if (const Result<String, EnvError> shellResult = GetEnv("SHELL"); !shellResult->empty())
shellPath = *shellResult;
else if (const Result<String, EnvError> loginShellResult = GetEnv("LOGINSHELL"); !loginShellResult->empty())
shellPath = *loginShellResult;
if (const Result<String, EnvError> msystemResult = GetEnv("MSYSTEM"); msystemResult && !msystemResult->empty()) {
String shellPath;
if (!shellPath.empty()) {
const usize lastSlash = shellPath.find_last_of("\\/");
String shellExe = (lastSlash != String::npos) ? shellPath.substr(lastSlash + 1) : shellPath;
if (const Result<String, EnvError> shellResult = GetEnv("SHELL"); shellResult && !shellResult->empty())
shellPath = *shellResult;
else if (const Result<String, EnvError> loginShellResult = GetEnv("LOGINSHELL");
loginShellResult && !loginShellResult->empty())
shellPath = *loginShellResult;
std::ranges::transform(shellExe, shellExe.begin(), [](const u8 c) { return std::tolower(c); });
if (!shellPath.empty()) {
const usize lastSlash = shellPath.find_last_of("\\/");
String shellExe = (lastSlash != String::npos) ? shellPath.substr(lastSlash + 1) : shellPath;
if (shellExe.ends_with(".exe"))
shellExe.resize(shellExe.length() - 4);
std::ranges::transform(shellExe, shellExe.begin(), [](const u8 c) {
return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
});
const auto iter =
std::ranges::find_if(msysShellMap, [&](const auto& pair) { return StringView { shellExe } == pair.first; });
if (shellExe.ends_with(".exe"))
shellExe.resize(shellExe.length() - 4);
if (iter != std::ranges::end(msysShellMap))
return String { iter->second };
const auto iter =
std::ranges::find_if(msysShellMap, [&](const auto& pair) { return StringView { shellExe } == pair.first; });
if (iter != std::ranges::end(msysShellMap))
return String { iter->second };
}
if (const Option<String> msysShell = FindShellInProcessTree(currentPid, msysShellMap))
return *msysShell;
return "MSYS2 Environment";
}
if (const Option<String> msysShell = FindShellInProcessTree(currentPid, msysShellMap))
return *msysShell;
if (const Option<String> windowsShell = FindShellInProcessTree(currentPid, windowsShellMap))
return *windowsShell;
} catch (const winrt::hresult_error& e) {
ERROR_LOG("WinRT error during shell detection: {}", winrt::to_string(e.message()));
} catch (const std::exception& e) { ERROR_LOG("Standard exception during shell detection: {}", e.what()); }
return "MSYS2 Environment";
}
if (const Option<String> windowsShell = FindShellInProcessTree(currentPid, windowsShellMap))
return *windowsShell;
return "Unknown Shell";
return None;
}
fn os::GetDiskUsage() -> Pair<u64, u64> {
fn os::GetDiskUsage() -> Result<DiskSpace, OsError> {
ULARGE_INTEGER freeBytes, totalBytes;
if (GetDiskFreeSpaceExW(L"C:\\", nullptr, &totalBytes, &freeBytes))
return { totalBytes.QuadPart - freeBytes.QuadPart, totalBytes.QuadPart };
return DiskSpace { .used_bytes = totalBytes.QuadPart - freeBytes.QuadPart, .total_bytes = totalBytes.QuadPart };
return { 0, 0 };
return Err(OsError { OsErrorCode::NotFound, "Failed to get disk usage" });
}
#endif