Merge pull request #298 from CarterLi/dev

TerminalShell: improve speed on Windows
This commit is contained in:
Linus Dierheimer
2022-10-15 19:49:44 +02:00
committed by GitHub
8 changed files with 191 additions and 44 deletions
+6
View File
@@ -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
+1 -1
View File
@@ -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, ' ');
+9 -18
View File
@@ -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);
}
}
}
+13 -1
View File
@@ -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);
+85 -3
View File
@@ -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
View File
@@ -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"
+4 -1
View File
@@ -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
{