mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
WM: uses SystemBasicProcessInformation if available
This commit is contained in:
@@ -114,70 +114,110 @@ static bool isProcessTrusted(DWORD processId, FFProcessType processType, UNICODE
|
||||
|
||||
#define ffStrEqualNWS(str, compareTo) (_wcsnicmp(str, L##compareTo, sizeof(compareTo) - 1) == 0)
|
||||
|
||||
const char* ffDetectWMPlugin(FFstrbuf* pluginName) {
|
||||
// Returns true if the process was recognized as a WM plugin and pluginName was set.
|
||||
static bool handleProcess(FFstrbuf* pluginName, uint32_t pid, const UNICODE_STRING* imageName) {
|
||||
alignas(UNICODE_STRING) uint8_t buffer[4096];
|
||||
UNICODE_STRING* filePath = (UNICODE_STRING*) buffer;
|
||||
FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr;
|
||||
|
||||
// Multiple attempts in case processes change while
|
||||
// we are in the middle of querying them.
|
||||
ULONG size = 0;
|
||||
for (int attempts = 0;; ++attempts) {
|
||||
if (size) {
|
||||
pstart = (SYSTEM_PROCESS_INFORMATION*) realloc(pstart, size);
|
||||
assert(pstart);
|
||||
}
|
||||
NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size);
|
||||
if (NT_SUCCESS(status)) {
|
||||
break;
|
||||
} else if (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) {
|
||||
size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5;
|
||||
if (imageName->Length == strlen("FancyWM-GUI.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(imageName->Buffer, "FancyWM-GUI.exe") &&
|
||||
isProcessTrusted(pid, FF_PROCESS_TYPE_WINDOWS_STORE | FF_PROCESS_TYPE_GUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion && ffGetFileVersion(filePath->Buffer, nullptr, pluginName)) {
|
||||
ffStrbufPrependS(pluginName, "FancyWM ");
|
||||
} else {
|
||||
return "NtQuerySystemInformation(SystemProcessInformation) failed";
|
||||
ffStrbufSetStatic(pluginName, "FancyWM");
|
||||
}
|
||||
return true;
|
||||
} else if (imageName->Length == strlen("glazewm-watcher.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(imageName->Buffer, "glazewm-watcher.exe") &&
|
||||
isProcessTrusted(pid, FF_PROCESS_TYPE_SIGNED | FF_PROCESS_TYPE_GUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion && ffGetFileVersion(filePath->Buffer, nullptr, pluginName)) {
|
||||
ffStrbufPrependS(pluginName, "GlazeWM ");
|
||||
} else {
|
||||
ffStrbufSetStatic(pluginName, "GlazeWM");
|
||||
}
|
||||
return true;
|
||||
} else if (imageName->Length == strlen("komorebi.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(imageName->Buffer, "komorebi.exe") &&
|
||||
isProcessTrusted(pid, FF_PROCESS_TYPE_CUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion) {
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateNWS(filePath->Length / sizeof(wchar_t), filePath->Buffer);
|
||||
if (ffProcessAppendStdOut(pluginName, (char* const[]) {
|
||||
path.chars,
|
||||
"--version",
|
||||
nullptr,
|
||||
}) == nullptr) {
|
||||
ffStrbufSubstrBeforeFirstC(pluginName, '\n');
|
||||
}
|
||||
}
|
||||
if (pluginName->length == 0) {
|
||||
ffStrbufSetStatic(pluginName, "Komorebi");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (SYSTEM_PROCESS_INFORMATION* ptr = pstart;; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) {
|
||||
assert(ptr->ImageName.Length == 0 || ptr->ImageName.MaximumLength >= ptr->ImageName.Length + 2); // nullptr terminated
|
||||
if (ptr->ImageName.Length == strlen("FancyWM-GUI.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(ptr->ImageName.Buffer, "FancyWM-GUI.exe") &&
|
||||
isProcessTrusted((DWORD) (uintptr_t) ptr->UniqueProcessId, FF_PROCESS_TYPE_WINDOWS_STORE | FF_PROCESS_TYPE_GUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion && ffGetFileVersion(filePath->Buffer, nullptr, pluginName)) {
|
||||
ffStrbufPrependS(pluginName, "FancyWM ");
|
||||
} else {
|
||||
ffStrbufSetStatic(pluginName, "FancyWM");
|
||||
}
|
||||
break;
|
||||
} else if (ptr->ImageName.Length == strlen("glazewm-watcher.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(ptr->ImageName.Buffer, "glazewm-watcher.exe") &&
|
||||
isProcessTrusted((DWORD) (uintptr_t) ptr->UniqueProcessId, FF_PROCESS_TYPE_SIGNED | FF_PROCESS_TYPE_GUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion && ffGetFileVersion(filePath->Buffer, nullptr, pluginName)) {
|
||||
ffStrbufPrependS(pluginName, "GlazeWM ");
|
||||
} else {
|
||||
ffStrbufSetStatic(pluginName, "GlazeWM");
|
||||
}
|
||||
break;
|
||||
} else if (ptr->ImageName.Length == strlen("komorebi.exe") * sizeof(wchar_t) &&
|
||||
ffStrEqualNWS(ptr->ImageName.Buffer, "komorebi.exe") &&
|
||||
isProcessTrusted((DWORD) (uintptr_t) ptr->UniqueProcessId, FF_PROCESS_TYPE_CUI, filePath, sizeof(buffer))) {
|
||||
if (instance.config.general.detectVersion) {
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateNWS(filePath->Length / sizeof(wchar_t), filePath->Buffer);
|
||||
if (ffProcessAppendStdOut(pluginName, (char* const[]) {
|
||||
path.chars,
|
||||
"--version",
|
||||
nullptr,
|
||||
}) == nullptr) {
|
||||
ffStrbufSubstrBeforeFirstC(pluginName, '\n');
|
||||
}
|
||||
}
|
||||
if (pluginName->length == 0) {
|
||||
ffStrbufSetStatic(pluginName, "Komorebi");
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectWMPlugin(FFstrbuf* pluginName) {
|
||||
if (ffIsSystemBasicProcessInfoAvailable()) {
|
||||
// Unlike SystemProcessInformation, SystemBasicProcessInformation only returns processes
|
||||
// (no threads), so a single query with a modest buffer is enough.
|
||||
ULONG size = 0;
|
||||
if (NtQuerySystemInformation(SystemBasicProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) {
|
||||
goto fallback;
|
||||
}
|
||||
// The process table may change between the two calls; retry with a larger buffer.
|
||||
size += size / 8 + sizeof(SYSTEM_BASICPROCESS_INFORMATION);
|
||||
FF_AUTO_FREE SYSTEM_BASICPROCESS_INFORMATION* pstart = malloc(size);
|
||||
|
||||
if (!NT_SUCCESS(NtQuerySystemInformation(SystemBasicProcessInformation, pstart, size, &size))) {
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
if (ptr->NextEntryOffset == 0) {
|
||||
break;
|
||||
for (auto ptr = pstart;; ptr = (SYSTEM_BASICPROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) {
|
||||
assert(ptr >= pstart && (uint8_t*) ptr < (uint8_t*) pstart + size);
|
||||
if (handleProcess(pluginName, (uint32_t)(uintptr_t) ptr->UniqueProcessId, &ptr->ImageName)) {
|
||||
return nullptr;
|
||||
}
|
||||
// The last process in the list always has a NextEntryOffset of 0, even if the buffer was truncated.
|
||||
if (!ptr->NextEntryOffset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fallback:
|
||||
{
|
||||
FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr;
|
||||
|
||||
// Multiple attempts in case processes change while
|
||||
// we are in the middle of querying them.
|
||||
ULONG size = 0;
|
||||
for (int attempts = 0;; ++attempts) {
|
||||
if (size) {
|
||||
pstart = (SYSTEM_PROCESS_INFORMATION*) realloc(pstart, size);
|
||||
assert(pstart);
|
||||
}
|
||||
NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size);
|
||||
if (NT_SUCCESS(status)) {
|
||||
break;
|
||||
} else if (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) {
|
||||
size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5;
|
||||
} else {
|
||||
return "NtQuerySystemInformation(SystemProcessInformation) failed";
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ptr = pstart;; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) {
|
||||
assert(ptr->ImageName.Length == 0 || ptr->ImageName.MaximumLength >= ptr->ImageName.Length + 2); // nullptr terminated
|
||||
if (handleProcess(pluginName, (uint32_t)(uintptr_t) ptr->UniqueProcessId, &ptr->ImageName)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ptr->NextEntryOffset == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user