mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Merge pull request #298 from CarterLi/dev
TerminalShell: improve speed on Windows
This commit is contained in:
@@ -64,6 +64,7 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32"
|
||||
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF)
|
||||
cmake_dependent_option(USE_WIN_FAST_PPID_DETECTION "Use internal NTAPI instead of querying WMI to get PPID" ON "WIN32" OFF)
|
||||
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
@@ -523,7 +524,12 @@ elseif(WIN32)
|
||||
PRIVATE "opengl32"
|
||||
PRIVATE "wbemuuid"
|
||||
PRIVATE "ws2_32"
|
||||
PRIVATE "ntdll"
|
||||
PRIVATE "version"
|
||||
)
|
||||
if(USE_WIN_FAST_PPID_DETECTION)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_FAST_PPID_DETECTION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
|
||||
@@ -28,7 +28,7 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
};
|
||||
|
||||
FFstrbuf cmdline;
|
||||
ffStrbufInitS(&cmdline, argv[0]);
|
||||
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
|
||||
for(char* const* parg = &argv[1]; *parg; ++parg)
|
||||
{
|
||||
ffStrbufAppendC(&cmdline, ' ');
|
||||
|
||||
@@ -5,24 +5,10 @@
|
||||
|
||||
#include "localip.h"
|
||||
|
||||
static void addNewIp(FFlist* list, const wchar_t* name, const char* addr, bool ipv6)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
|
||||
int len = (int)wcslen(name);
|
||||
if(len > 0)
|
||||
{
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, name, len, NULL, 0, NULL, NULL);
|
||||
ffStrbufInitA(&ip->name, (uint32_t)size_needed + 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, name, len, ip->name.chars, size_needed, NULL, NULL);
|
||||
ip->name.length = (uint32_t)size_needed;
|
||||
ip->name.chars[size_needed] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufInitS(&ip->name, "*");
|
||||
}
|
||||
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInitS(&ip->addr, addr);
|
||||
ip->ipv6 = ipv6;
|
||||
}
|
||||
@@ -64,6 +50,11 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK && !instance->config.localIpShowLoop)
|
||||
continue;
|
||||
|
||||
char name[128];
|
||||
WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL);
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next)
|
||||
{
|
||||
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
|
||||
@@ -75,7 +66,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
|
||||
addNewIp(results, name, addressBuffer, false);
|
||||
}
|
||||
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
@@ -86,7 +77,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
|
||||
addNewIp(results, name, addressBuffer, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,18 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
uint32_t index = ffStrbufFirstIndexC(&os->variant, ' ');
|
||||
ffStrbufAppendNS(&os->version, index, os->variant.chars);
|
||||
ffStrbufSubstrAfter(&os->variant, index);
|
||||
|
||||
// Windows Server 20xx Rx
|
||||
if(ffStrbufEndsWithC(&os->prettyName, 'r'))
|
||||
{
|
||||
if(os->variant.chars[0] == 'R' &&
|
||||
isdigit(os->variant.chars[1]) &&
|
||||
(os->variant.chars[2] == '\0' || os->variant.chars[2] == ' '))
|
||||
{
|
||||
ffStrbufAppendF(&os->version, " R%c", os->variant.chars[1]);
|
||||
ffStrbufSubstrAfter(&os->variant, strlen("Rx ") - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -59,7 +71,7 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
ffStrbufClear(&os->variant);
|
||||
}
|
||||
|
||||
ffStrbufAppendF(&os->id, "Windows %*s", os->version.length, os->version.chars);
|
||||
ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars);
|
||||
|
||||
ffGetWmiObjString(pclsObj, L"BuildNumber", &os->buildID);
|
||||
ffGetWmiObjString(pclsObj, L"OSArchitecture", &os->architecture);
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <winver.h>
|
||||
|
||||
static bool getFileVersion(const char* exePath, FFstrbuf* version)
|
||||
{
|
||||
DWORD handle;
|
||||
DWORD size = GetFileVersionInfoSizeA(exePath, &handle);
|
||||
if(size > 0)
|
||||
{
|
||||
void* versionData = malloc(size);
|
||||
if(GetFileVersionInfoA(exePath, handle, size, versionData))
|
||||
{
|
||||
VS_FIXEDFILEINFO* verInfo;
|
||||
UINT len;
|
||||
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
|
||||
{
|
||||
ffStrbufAppendF(version, "%u.%u.%u.%u",
|
||||
(unsigned)(( verInfo->dwFileVersionMS >> 16 ) & 0xffff),
|
||||
(unsigned)(( verInfo->dwFileVersionMS >> 0 ) & 0xffff),
|
||||
(unsigned)(( verInfo->dwFileVersionLS >> 16 ) & 0xffff),
|
||||
(unsigned)(( verInfo->dwFileVersionLS >> 0 ) & 0xffff)
|
||||
);
|
||||
free(versionData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
free(versionData);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void getShellVersionBash(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
ffProcessAppendStdOut(version, (char* const[]) {
|
||||
@@ -25,7 +60,7 @@ static void getShellVersionZsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
ffStrbufSubstrAfterFirstC(version, ' ');
|
||||
}
|
||||
|
||||
static void getShellVersionFishPwsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
static void getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
@@ -36,6 +71,43 @@ static void getShellVersionFishPwsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
}
|
||||
|
||||
static void getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if(getFileVersion(exe->chars, version))
|
||||
return;
|
||||
#endif
|
||||
|
||||
ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
ffStrbufTrimRight(version, '\n');
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"-NoLogo",
|
||||
"-NoProfile",
|
||||
"-Command",
|
||||
"$PSVersionTable.PSVersion.ToString()",
|
||||
NULL
|
||||
});
|
||||
ffStrbufTrimRight(version, '\n');
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
}
|
||||
|
||||
static void getShellVersionCmd(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
getFileVersion(exe->chars, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void getShellVersionNu(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
ffProcessAppendStdOut(version, (char* const[]) {
|
||||
@@ -52,10 +124,20 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
|
||||
getShellVersionBash(exe, version);
|
||||
else if(strcasecmp(exeName, "zsh") == 0)
|
||||
getShellVersionZsh(exe, version);
|
||||
else if(strcasecmp(exeName, "fish") == 0 || strcasecmp(exeName, "pwsh") == 0)
|
||||
getShellVersionFishPwsh(exe, version);
|
||||
else if(strcasecmp(exeName, "fish") == 0)
|
||||
getShellVersionFish(exe, version);
|
||||
else if(strcasecmp(exeName, "pwsh") == 0)
|
||||
getShellVersionPwsh(exe, version);
|
||||
else if(strcasecmp(exeName, "nu") == 0)
|
||||
getShellVersionNu(exe, version);
|
||||
|
||||
#ifdef _WIN32
|
||||
else if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0)
|
||||
getShellVersionWinPowerShell(exe, version);
|
||||
else if(strcasecmp(exeName, "cmd") == 0)
|
||||
getShellVersionCmd(exe, version);
|
||||
#endif
|
||||
|
||||
else
|
||||
ok = false;
|
||||
return ok;
|
||||
|
||||
@@ -3,20 +3,68 @@ extern "C" {
|
||||
#include "common/processing.h"
|
||||
#include "common/thread.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
struct ProcessInfo
|
||||
{
|
||||
uint32_t pid;
|
||||
FFstrbuf psName;
|
||||
};
|
||||
#include <chrono>
|
||||
|
||||
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe)
|
||||
#ifdef FF_USE_WIN_FAST_PPID_DETECTION
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName)
|
||||
{
|
||||
HANDLE hProcess = pid == 0
|
||||
? GetCurrentProcess()
|
||||
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid);
|
||||
|
||||
if(ppid)
|
||||
{
|
||||
PROCESS_BASIC_INFORMATION info;
|
||||
ULONG size;
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessBasicInformation, &info, sizeof(info), &size)))
|
||||
{
|
||||
assert(size == sizeof(info));
|
||||
*ppid = (uint32_t)info.InheritedFromUniqueProcessId;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(exe)
|
||||
{
|
||||
DWORD bufSize = exe->allocated;
|
||||
if(QueryFullProcessImageNameA(hProcess, 0, exe->chars, &bufSize))
|
||||
exe->length = bufSize;
|
||||
else
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(pname && exeName)
|
||||
{
|
||||
*exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1;
|
||||
ffStrbufSetS(pname, *exeName);
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName)
|
||||
{
|
||||
if(pid == 0)
|
||||
pid = GetCurrentProcessId();
|
||||
|
||||
wchar_t query[256] = {};
|
||||
swprintf(query, 256, L"SELECT %ls %ls ParentProcessId FROM Win32_Process WHERE ProcessId = %" PRIu32,
|
||||
pname ? L"Name," : L"",
|
||||
@@ -49,20 +97,26 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
|
||||
if(exe)
|
||||
ffGetWmiObjString(pclsObj, L"ExecutablePath", exe);
|
||||
|
||||
if(exeName)
|
||||
{
|
||||
*exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1;
|
||||
}
|
||||
|
||||
pclsObj->Release();
|
||||
pEnumerator->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
|
||||
|
||||
static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
|
||||
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe))
|
||||
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe, &result->shellExeName))
|
||||
return 0;
|
||||
result->shellExeName = result->shellExe.chars + ffStrbufLastIndexC(&result->shellExe, '\\') + 1;
|
||||
|
||||
ffStrbufSet(&result->shellPrettyName, &result->shellProcessName);
|
||||
if(ffStrbufEndsWithIgnCaseS(&result->shellPrettyName, ".exe"))
|
||||
@@ -113,9 +167,8 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
|
||||
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe))
|
||||
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName))
|
||||
return 0;
|
||||
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\');
|
||||
|
||||
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
|
||||
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
|
||||
@@ -135,7 +188,7 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
ffStrbufClear(&result->terminalProcessName);
|
||||
ffStrbufClear(&result->terminalPrettyName);
|
||||
ffStrbufClear(&result->terminalExe);
|
||||
result->terminalExeName = nullptr;
|
||||
result->terminalExeName = "";
|
||||
return getTerminalInfo(result, ppid);
|
||||
}
|
||||
|
||||
@@ -212,21 +265,21 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
|
||||
|
||||
ffStrbufInit(&result.shellProcessName);
|
||||
ffStrbufInitA(&result.shellExe, 128);
|
||||
result.shellExeName = result.shellExe.chars;
|
||||
result.shellExeName = "";
|
||||
ffStrbufInit(&result.shellPrettyName);
|
||||
ffStrbufInit(&result.shellVersion);
|
||||
|
||||
ffStrbufInit(&result.terminalProcessName);
|
||||
ffStrbufInitA(&result.terminalExe, 128);
|
||||
result.terminalExeName = result.terminalExe.chars;
|
||||
result.terminalExeName = "";
|
||||
ffStrbufInit(&result.terminalPrettyName);
|
||||
|
||||
ffStrbufInit(&result.userShellExe);
|
||||
result.userShellExeName = result.userShellExe.chars;
|
||||
result.userShellExeName = "";
|
||||
ffStrbufInit(&result.userShellVersion);
|
||||
|
||||
uint32_t ppid = GetCurrentProcessId();
|
||||
if(!getProcessInfo(ppid, &ppid, nullptr, nullptr))
|
||||
uint32_t ppid;
|
||||
if(!getProcessInfo(0, &ppid, nullptr, nullptr, nullptr))
|
||||
goto exit;
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
|
||||
+3
-3
@@ -1280,7 +1280,7 @@ static const FFlogo* getLogoMsys2()
|
||||
static const FFlogo* getLogoWindows11()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows 11")
|
||||
FF_LOGO_NAMES("Windows 11", "Windows Server 2022")
|
||||
FF_LOGO_LINES(
|
||||
"$1\n"
|
||||
"################ ################\n"
|
||||
@@ -1310,7 +1310,7 @@ static const FFlogo* getLogoWindows11()
|
||||
static const FFlogo* getLogoWindows8()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows 8", "Windows 8.1", "Windows 10")
|
||||
FF_LOGO_NAMES("Windows 8", "Windows 8.1", "Windows 10", "Windows Server 2012", "Windows Server 2012 R2", "Windows Server 2016", "Windows Server 2019")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ..,\n"
|
||||
" ....,,:;+ccllll\n"
|
||||
@@ -1343,7 +1343,7 @@ static const FFlogo* getLogoWindows8()
|
||||
static const FFlogo* getLogoWindows()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("Windows")
|
||||
FF_LOGO_NAMES("Windows", "Windows 7", "Windows Server 2008", "Windows Server 2008 R2")
|
||||
FF_LOGO_LINES(
|
||||
"$1 ,.=:!!t3Z3z.,\n"
|
||||
" :tt:::tt333EE3\n"
|
||||
|
||||
@@ -33,7 +33,10 @@ void ffPrintLocalIp(FFinstance* instance)
|
||||
|
||||
if(instance->config.localIP.key.length == 0)
|
||||
{
|
||||
ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars);
|
||||
if(ip->name.length)
|
||||
ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars);
|
||||
else
|
||||
ffStrbufSetS(&key, FF_LOCALIP_MODULE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user