From 61cdfcabf8c0a0d4dfadc969c9f03eeffd170d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Feb 2026 14:28:11 +0800 Subject: [PATCH] Windows: uses `SHGetKnownFolderPath` instead of the unreliable `getenv` --- src/common/impl/FFPlatform_windows.c | 4 +- src/detection/packages/packages_windows.c | 8 +++- .../terminalshell/terminalshell_windows.c | 37 +++++++++++++------ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/common/impl/FFPlatform_windows.c b/src/common/impl/FFPlatform_windows.c index cd138dc22..25062ba83 100644 --- a/src/common/impl/FFPlatform_windows.c +++ b/src/common/impl/FFPlatform_windows.c @@ -70,15 +70,15 @@ static void getCacheDir(FFPlatform* platform) static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) { PWSTR pPath = NULL; - if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) + if (SUCCEEDED(SHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT, NULL, &pPath))) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath); + CoTaskMemFree(pPath); ffStrbufReplaceAllC(&buffer, '\\', '/'); ffStrbufEnsureEndsWithC(&buffer, '/'); if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual)) ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer); } - CoTaskMemFree(pPath); } static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index ec4c6e1af..5c2b639a4 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -10,6 +10,7 @@ #include #include "common/windows/nt.h" #include +#include static uint32_t getNumElements(const char* searchPath, DWORD type, const wchar_t* ignore) { @@ -108,7 +109,12 @@ static void detectScoop(FFPackagesResult* result) ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "global_path")); if (scoopPath.length == 0) { - ffStrbufSetS(&scoopPath, getenv("ProgramData")); + PWSTR pPath = NULL; + if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_ProgramData, KF_FLAG_DEFAULT, NULL, &pPath))) + { + ffStrbufSetWS(&scoopPath, pPath); + CoTaskMemFree(pPath); + } ffStrbufAppendS(&scoopPath, "/scoop"); } ffStrbufAppendS(&scoopPath, "/apps/"); diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index 16aac7d90..9384b41bb 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -14,6 +14,7 @@ #include #include #include +#include bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); @@ -189,17 +190,29 @@ static bool detectDefaultTerminal(FFTerminalResult* result) { ffStrbufSetS(&result->processName, "WindowsTerminal.exe"); ffStrbufSetS(&result->prettyName, "WindowsTerminal"); - ffStrbufSetF(&result->exe, "%s\\WindowsApps\\%s\\WindowsTerminal.exe", getenv("ProgramFiles"), path.chars); - if(ffPathExists(result->exe.chars, FF_PATHTYPE_FILE)) + + PWSTR programFiles = NULL; + if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFiles))) { - result->exeName = result->exe.chars + ffStrbufLastIndexC(&result->exe, '\\') + 1; - ffStrbufSet(&result->exePath, &result->exe); - } - else - { - ffStrbufDestroy(&result->exe); - ffStrbufInitMove(&result->exe, &path); - result->exeName = ""; + ffStrbufSetWS(&result->exe, programFiles); + CoTaskMemFree(programFiles); + programFiles = NULL; + + ffStrbufAppendS(&result->exe, "\\WindowsApps\\"); + ffStrbufAppend(&result->exe, &path); + ffStrbufAppendS(&result->exe, "\\WindowsTerminal.exe"); + + if(ffPathExists(result->exe.chars, FF_PATHTYPE_FILE)) + { + result->exeName = result->exe.chars + ffStrbufLastIndexC(&result->exe, '\\') + 1; + ffStrbufSet(&result->exePath, &result->exe); + } + else + { + ffStrbufDestroy(&result->exe); + ffStrbufInitMove(&result->exe, &path); + result->exeName = ""; + } } return true; } @@ -214,11 +227,11 @@ conhost:; { // For Windows Terminal, it reports the PID of OpenConsole if(ffProcessGetInfoWindows((uint32_t) conhostPid, NULL, &result->processName, &result->exe, &result->exeName, &result->exePath, NULL)) - { + { ffStrbufSet(&result->prettyName, &result->processName); if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe")) ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4); - return true; + return true; } }