ohmu
·
2026-10-15
1#pragma once
2
3#include "fastfetch.h"
4#include "common/io.h"
5
6#include <wchar.h> // ffGetProfilePath() takes a SID as a wide string
7
8// The known folders fastfetch needs. They are spelled out instead of taking a REFKNOWNFOLDERID so
9// that this header does not have to drag in <shlobj.h> -- the call sites include it for reasons of
10// their own, and a header that only works when <windows.h> came first is a trap.
11typedef enum FFKnownFolder : uint8_t {
12 FF_KNOWN_FOLDER_LOCAL_APP_DATA,
13 FF_KNOWN_FOLDER_ROAMING_APP_DATA,
14 FF_KNOWN_FOLDER_PROGRAM_DATA,
15 FF_KNOWN_FOLDER_PROGRAM_FILES,
16 FF_KNOWN_FOLDER_COUNT,
17} FFKnownFolder;
18
19// Resolves a known folder without initializing the shell.
20//
21// The first SHGetKnownFolderPath() call in a process costs ~2.4 ms (measured on Windows 10 22H2):
22// the shell's known-folder machinery is built on demand, and whichever folder is asked for first
23// pays for it. Every later call is free, so a process that needs a handful of folders pays that
24// price once and can never amortize it. Each folder below is instead one registry value or one
25// environment variable away -- ~0.03 ms for all of them together -- so the shell is never touched.
26//
27// The answer is cached: these five folders are asked for about a dozen times per process, and each
28// answer is a pure function of the registry and this process' environment. That is safe without a
29// lock, because nothing that resolves a known folder ever runs on the one thread fastfetch creates.
30//
31// Returns false, leaving `result` untouched, when the value is missing or unusable, so that the
32// caller keeps whatever fallback it had for the shell API failing. The path uses backslashes,
33// exactly like SHGetKnownFolderPath().
34bool ffGetKnownFolderPath(FFKnownFolder folder, FFstrbuf* result);
35
36// Resolves the profile directory recorded for `sidW`, a SID string as produced by
37// RtlConvertSidToUnicodeString().
38//
39// There is no FF_KNOWN_FOLDER_PROFILE because the caller already has the SID:
40// FFPlatform_windows.c resolves it once for `platform->sid`, and deriving it a second time here
41// would mean a second NtQueryInformationToken(). The answer is deliberately not cached -- this is
42// called once per process, and from one place.
43//
44// Returns false, leaving `result` untouched, when the value is missing or unusable, so that the
45// caller keeps whatever fallback it had for the shell API failing. The path uses backslashes,
46// exactly like SHGetKnownFolderPath().
47bool ffGetProfilePath(const wchar_t* sidW, FFstrbuf* result);