Global (Windows): eliminates SHGetKnownFolderPath

This commit is contained in:
Carter Li
2026-09-28 23:02:34 +08:00
parent cdbe8f54c6
commit 4fb57bb39b
8 changed files with 353 additions and 83 deletions
+4 -6
View File
@@ -2,6 +2,7 @@
#include "common/processing.h"
#include "common/strutil.h"
#include "common/path.h"
#include "common/windows/folders.h"
#include "common/windows/unicode.h"
#include "common/windows/registry.h"
#include "common/mallocHelper.h"
@@ -11,7 +12,6 @@
#include <windows.h>
#include "common/windows/nt.h"
#include <ntstatus.h>
#include <shlobj.h>
static uint32_t getNumElements(const char* searchPath, DWORD type, const wchar_t* ignore) {
FF_AUTO_CLOSE_FD HANDLE dfd = CreateFileA(searchPath, FILE_LIST_DIRECTORY | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
@@ -120,11 +120,9 @@ static void detectScoop(FFPackagesResult* result) {
ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "global_path"));
}
if (scoopPath.length == 0) {
PWSTR pPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_ProgramData, KF_FLAG_DEFAULT, nullptr, &pPath))) {
ffStrbufSetWS(&scoopPath, pPath);
CoTaskMemFree(pPath);
}
// Leaving `scoopPath` empty when the lookup fails makes `getNumElements` report 0, which
// is what the shell API failing used to do as well.
ffGetKnownFolderPath(FF_KNOWN_FOLDER_PROGRAM_DATA, &scoopPath);
ffStrbufAppendS(&scoopPath, "/scoop");
}
ffStrbufAppendS(&scoopPath, "/apps/");
@@ -3,13 +3,13 @@
#include "common/path.h"
#include "common/processing.h"
#include "common/properties.h"
#include "common/windows/folders.h"
#include "common/windows/unicode.h"
#include "common/windows/registry.h"
#include "common/strutil.h"
#include "detection/terminalshell/terminalshell.h"
#include "terminalfont.h"
#include <shlobj.h>
#include <windows.h>
#include <stdlib.h>
@@ -225,13 +225,11 @@ static void detectWTProfileFromFragmentsIn(const FFstrbuf* fragmentDir, const FF
static void detectFromWTFragments(const FFstrbuf* wtProfileId, FFTerminalFontWT* result) {
// Windows Terminal merges the user scoped fragments before the machine scoped ones,
// so the user scoped fragments are more important
static const KNOWNFOLDERID* const fragmentFolderIds[] = { &FOLDERID_LocalAppData, &FOLDERID_ProgramData };
static const FFKnownFolder fragmentFolders[] = { FF_KNOWN_FOLDER_LOCAL_APP_DATA, FF_KNOWN_FOLDER_PROGRAM_DATA };
for (uint32_t i = 0; i < ARRAY_SIZE(fragmentFolderIds); ++i) {
PWSTR folderW = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(fragmentFolderIds[i], KF_FLAG_DEFAULT, nullptr, &folderW))) {
FF_STRBUF_AUTO_DESTROY fragmentDir = ffStrbufCreateWS(folderW);
CoTaskMemFree(folderW);
for (uint32_t i = 0; i < ARRAY_SIZE(fragmentFolders); ++i) {
FF_STRBUF_AUTO_DESTROY fragmentDir = ffStrbufCreate();
if (ffGetKnownFolderPath(fragmentFolders[i], &fragmentDir)) {
ffStrbufAppendS(&fragmentDir, "\\Microsoft\\Windows Terminal\\Fragments\\");
if (ffPathExists(fragmentDir.chars, FF_PATHTYPE_DIRECTORY)) {
@@ -258,11 +256,7 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon
error = "Error reading Windows Terminal portable settings JSON file";
}
} else {
PWSTR localAppDataW = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, &localAppDataW))) {
ffStrbufSetWS(&jsonPath, localAppDataW);
CoTaskMemFree(localAppDataW);
if (ffGetKnownFolderPath(FF_KNOWN_FOLDER_LOCAL_APP_DATA, &jsonPath)) {
if (ffStrbufContainIgnCaseS(terminalExe, "_8wekyb3d8bbwe\\")) {
// Microsoft Store version
if (ffStrbufContainIgnCaseS(terminalExe, ".WindowsTerminalPreview_")) {
@@ -4,6 +4,7 @@
#include "common/processing.h"
#include "common/thread.h"
#include "common/mallocHelper.h"
#include "common/windows/folders.h"
#include "common/windows/registry.h"
#include "common/windows/unicode.h"
#include "common/windows/version.h"
@@ -16,7 +17,6 @@
#include <tlhelp32.h>
#include <ntstatus.h>
#include <winternl.h>
#include <shlobj.h>
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid) {
uint32_t ppid = 0;
@@ -182,12 +182,7 @@ static bool detectDefaultTerminal(FFTerminalResult* result) {
ffStrbufSetS(&result->processName, "WindowsTerminal.exe");
ffStrbufSetS(&result->prettyName, "WindowsTerminal");
PWSTR programFiles = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, nullptr, &programFiles))) {
ffStrbufSetWS(&result->exe, programFiles);
CoTaskMemFree(programFiles);
programFiles = nullptr;
if (ffGetKnownFolderPath(FF_KNOWN_FOLDER_PROGRAM_FILES, &result->exe)) {
ffStrbufAppendS(&result->exe, "\\WindowsApps\\");
ffStrbufAppend(&result->exe, &path);
ffStrbufAppendS(&result->exe, "\\WindowsTerminal.exe");
+14 -16
View File
@@ -3,6 +3,7 @@
#include "common/io.h"
#include "common/library.h"
#include "common/processing.h"
#include "common/windows/folders.h"
#include "common/windows/nt.h"
#include "common/windows/unicode.h"
#include "common/windows/version.h"
@@ -10,7 +11,6 @@
#include <stdalign.h>
#include <windows.h>
#include <ntstatus.h>
#include <shlobj.h>
#include <softpub.h>
typedef enum {
@@ -69,16 +69,18 @@ static bool isProcessTrusted(DWORD processId, FFProcessType processType, UNICODE
static wchar_t windowsAppsPath[MAX_PATH];
static uint32_t windowsAppsPathLen;
if (windowsAppsPathLen == 0) {
PWSTR pPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, nullptr, &pPath))) {
windowsAppsPathLen = (uint32_t) wcslen(pPath);
memcpy(windowsAppsPath, pPath, windowsAppsPathLen * sizeof(wchar_t));
memcpy(windowsAppsPath + windowsAppsPathLen, L"\\WindowsApps\\", sizeof(L"\\WindowsApps\\"));
windowsAppsPathLen += strlen("\\WindowsApps\\");
FF_STRBUF_AUTO_DESTROY programFiles = ffStrbufCreate();
ULONG length = 0; // in bytes, including the null terminator
if (ffGetKnownFolderPath(FF_KNOWN_FOLDER_PROGRAM_FILES, &programFiles)) {
ffStrbufAppendS(&programFiles, "\\WindowsApps\\");
if (NT_SUCCESS(RtlUTF8ToUnicodeN(windowsAppsPath, (ULONG) sizeof(windowsAppsPath), &length, programFiles.chars, (ULONG) programFiles.length + 1))) {
windowsAppsPathLen = (uint32_t) (length / sizeof(wchar_t) - 1);
} else {
windowsAppsPathLen = -1u;
}
} else {
windowsAppsPathLen = -1u;
}
CoTaskMemFree(pPath);
}
if (windowsAppsPathLen != -1u &&
(buffer->Length <= windowsAppsPathLen * sizeof(wchar_t) || // Path is too short to be in WindowsApps
@@ -230,14 +232,10 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, [[maybe_
}
if (ffStrbufEqualS(wmName, "dwm.exe")) {
PWSTR pPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_System, KF_FLAG_DEFAULT, nullptr, &pPath))) {
wchar_t fullPath[MAX_PATH];
wcscpy(fullPath, pPath);
wcscat(fullPath, L"\\dwm.exe");
ffGetFileVersion(fullPath, nullptr, result);
}
CoTaskMemFree(pPath);
wchar_t exePath[MAX_PATH];
_snwprintf(exePath, ARRAY_SIZE(exePath), L"%ls\\system32\\%ls", (const wchar_t*) SharedUserData->NtSystemRoot, L"dwm.exe");
ffGetFileVersion(exePath, nullptr, result);
return nullptr;
}
return "Not supported on this platform";