2023-01-15 15:57:26 +01:00
|
|
|
#include "FFPlatform_private.h"
|
2023-06-29 10:31:20 +08:00
|
|
|
#include "common/io/io.h"
|
2023-02-02 19:17:51 +08:00
|
|
|
#include "util/stringUtils.h"
|
2023-05-27 22:30:38 +08:00
|
|
|
#include "util/windows/unicode.h"
|
2023-09-23 11:51:37 +08:00
|
|
|
#include "util/windows/registry.h"
|
2024-05-17 21:30:47 +08:00
|
|
|
#include "util/windows/nt.h"
|
2023-01-15 15:57:26 +01:00
|
|
|
|
|
|
|
|
#include <Windows.h>
|
|
|
|
|
#include <shlobj.h>
|
2023-06-29 10:31:20 +08:00
|
|
|
|
2023-08-24 13:47:20 +08:00
|
|
|
static void getExePath(FFPlatform* platform)
|
|
|
|
|
{
|
|
|
|
|
wchar_t exePathW[MAX_PATH];
|
|
|
|
|
DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH);
|
|
|
|
|
if (exePathWLen == 0 && exePathWLen >= MAX_PATH) return;
|
|
|
|
|
|
2024-01-28 09:56:36 +08:00
|
|
|
FF_AUTO_CLOSE_FD HANDLE hPath = CreateFileW(exePathW, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
|
|
|
|
if (hPath != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
DWORD len = GetFinalPathNameByHandleW(hPath, exePathW, MAX_PATH, FILE_NAME_OPENED);
|
|
|
|
|
if (len > 0 && len < MAX_PATH)
|
|
|
|
|
exePathWLen = len;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-24 13:47:20 +08:00
|
|
|
ffStrbufSetNWS(&platform->exePath, exePathWLen, exePathW);
|
|
|
|
|
if (ffStrbufStartsWithS(&platform->exePath, "\\\\?\\"))
|
|
|
|
|
ffStrbufSubstrAfter(&platform->exePath, 3);
|
|
|
|
|
ffStrbufReplaceAllC(&platform->exePath, '\\', '/');
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-15 15:57:26 +01:00
|
|
|
static void getHomeDir(FFPlatform* platform)
|
|
|
|
|
{
|
|
|
|
|
PWSTR pPath;
|
|
|
|
|
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath)))
|
|
|
|
|
{
|
2023-01-15 16:26:08 +01:00
|
|
|
ffStrbufSetWS(&platform->homeDir, pPath);
|
|
|
|
|
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
|
|
|
|
|
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
|
2024-02-05 19:59:16 +08:00
|
|
|
CoTaskMemFree(pPath);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ffStrbufSetS(&platform->homeDir, getenv("USERPROFILE"));
|
|
|
|
|
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
|
|
|
|
|
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getCacheDir(FFPlatform* platform)
|
|
|
|
|
{
|
|
|
|
|
PWSTR pPath;
|
|
|
|
|
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath)))
|
|
|
|
|
{
|
2023-01-15 16:26:08 +01:00
|
|
|
ffStrbufSetWS(&platform->cacheDir, pPath);
|
|
|
|
|
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
|
|
|
|
|
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
|
2024-02-05 19:59:16 +08:00
|
|
|
CoTaskMemFree(pPath);
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-01-15 16:26:08 +01:00
|
|
|
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
|
|
|
|
|
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
|
|
|
|
|
{
|
|
|
|
|
PWSTR pPath;
|
|
|
|
|
if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
|
|
|
|
|
{
|
2023-06-29 10:31:20 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath);
|
|
|
|
|
ffStrbufReplaceAllC(&buffer, '\\', '/');
|
|
|
|
|
ffStrbufEnsureEndsWithC(&buffer, '/');
|
|
|
|
|
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
|
|
|
|
|
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
|
2024-02-05 19:59:16 +08:00
|
|
|
CoTaskMemFree(pPath);
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
|
|
|
|
|
{
|
|
|
|
|
const char* value = getenv(env);
|
|
|
|
|
if(!ffStrSet(value))
|
|
|
|
|
return;
|
|
|
|
|
|
2023-06-29 10:31:20 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateA(64);
|
|
|
|
|
ffStrbufAppendS(&buffer, value);
|
|
|
|
|
ffStrbufReplaceAllC(&buffer, '\\', '/');
|
|
|
|
|
ffStrbufEnsureEndsWithC(&buffer, '/');
|
|
|
|
|
if (suffix)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufAppendS(&buffer, suffix);
|
|
|
|
|
ffStrbufEnsureEndsWithC(&buffer, '/');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY) && !ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
|
|
|
|
|
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getConfigDirs(FFPlatform* platform)
|
|
|
|
|
{
|
2023-02-06 22:45:55 +08:00
|
|
|
if(getenv("MSYSTEM"))
|
2023-01-15 15:57:26 +01:00
|
|
|
{
|
|
|
|
|
// We are in MSYS2 / Git Bash
|
|
|
|
|
platformPathAddEnvSuffix(&platform->configDirs, "HOME", ".config/");
|
2023-06-29 10:31:20 +08:00
|
|
|
platformPathAddEnvSuffix(&platform->configDirs, "HOME", NULL);
|
2023-02-06 22:45:55 +08:00
|
|
|
platformPathAddEnvSuffix(&platform->configDirs, "MINGW_PREFIX", "etc");
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-06 22:45:55 +08:00
|
|
|
ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
|
2023-06-29 10:31:20 +08:00
|
|
|
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_ProgramData);
|
2023-02-06 22:45:55 +08:00
|
|
|
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData);
|
|
|
|
|
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData);
|
|
|
|
|
ffPlatformPathAddHome(&platform->configDirs, platform, "");
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-15 16:45:16 +01:00
|
|
|
static void getDataDirs(FFPlatform* platform)
|
2023-01-15 15:57:26 +01:00
|
|
|
{
|
|
|
|
|
if(getenv("MSYSTEM") && getenv("HOME"))
|
|
|
|
|
{
|
|
|
|
|
// We are in MSYS2 / Git Bash
|
|
|
|
|
platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ".local/share/");
|
2023-06-29 10:31:20 +08:00
|
|
|
platformPathAddEnvSuffix(&platform->dataDirs, "HOME", NULL);
|
2023-02-06 22:45:55 +08:00
|
|
|
platformPathAddEnvSuffix(&platform->dataDirs, "MINGW_PREFIX", "share");
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
2023-02-06 22:45:55 +08:00
|
|
|
ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/");
|
2023-06-29 10:31:20 +08:00
|
|
|
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_ProgramData);
|
2023-02-06 22:45:55 +08:00
|
|
|
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData);
|
|
|
|
|
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData);
|
|
|
|
|
ffPlatformPathAddHome(&platform->dataDirs, platform, "");
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getUserName(FFPlatform* platform)
|
|
|
|
|
{
|
2024-02-05 19:59:16 +08:00
|
|
|
const char* userName = getenv("USERNAME");
|
|
|
|
|
if (ffStrSet(userName))
|
|
|
|
|
ffStrbufSetS(&platform->userName, userName);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
wchar_t buffer[128];
|
|
|
|
|
DWORD len = sizeof(buffer) / sizeof(*buffer);
|
|
|
|
|
if(GetUserNameW(buffer, &len))
|
|
|
|
|
ffStrbufSetWS(&platform->userName, buffer);
|
|
|
|
|
}
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getHostName(FFPlatform* platform)
|
|
|
|
|
{
|
2023-07-30 12:38:47 +08:00
|
|
|
wchar_t buffer[128];
|
|
|
|
|
DWORD len = sizeof(buffer) / sizeof(*buffer);
|
|
|
|
|
if(GetComputerNameExW(ComputerNameDnsHostname, buffer, &len))
|
|
|
|
|
ffStrbufSetWS(&platform->hostName, buffer);
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-09-18 13:52:25 +08:00
|
|
|
static void getUserShell(FFPlatform* platform)
|
2023-01-15 15:57:26 +01:00
|
|
|
{
|
2023-09-18 13:52:25 +08:00
|
|
|
// Works in MSYS2
|
|
|
|
|
ffStrbufAppendS(&platform->userShell, getenv("SHELL"));
|
|
|
|
|
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getSystemReleaseAndVersion(FFPlatform* platform)
|
|
|
|
|
{
|
2023-09-23 11:51:37 +08:00
|
|
|
RTL_OSVERSIONINFOW osVersion = { .dwOSVersionInfoSize = sizeof(osVersion) };
|
|
|
|
|
if (!NT_SUCCESS(RtlGetVersion(&osVersion)))
|
2023-01-15 15:57:26 +01:00
|
|
|
return;
|
|
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
|
|
|
|
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL))
|
|
|
|
|
return;
|
2023-01-15 15:57:26 +01:00
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
uint32_t ubr = 0;
|
|
|
|
|
ffRegReadUint(hKey, L"UBR", &ubr, NULL);
|
2023-01-15 15:57:26 +01:00
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
ffStrbufAppendF(&platform->systemRelease,
|
|
|
|
|
"%u.%u.%u.%u",
|
|
|
|
|
(unsigned) osVersion.dwMajorVersion,
|
|
|
|
|
(unsigned) osVersion.dwMinorVersion,
|
|
|
|
|
(unsigned) osVersion.dwBuildNumber,
|
|
|
|
|
(unsigned) ubr);
|
2023-01-15 15:57:26 +01:00
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
ffStrbufInit(&platform->systemDisplayVersion);
|
2024-05-17 10:02:42 +08:00
|
|
|
if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &platform->systemDisplayVersion, NULL))
|
|
|
|
|
{
|
|
|
|
|
if (osVersion.szCSDVersion[0])
|
|
|
|
|
ffStrbufSetWS(&platform->systemDisplayVersion, osVersion.szCSDVersion);
|
|
|
|
|
else
|
|
|
|
|
ffRegReadStrbuf(hKey, L"ReleaseId", &platform->systemDisplayVersion, NULL); // For old Windows 10
|
|
|
|
|
}
|
2023-01-15 15:57:26 +01:00
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
ffRegReadStrbuf(hKey, L"BuildLabEx", &platform->systemVersion, NULL);
|
2023-01-15 15:57:26 +01:00
|
|
|
|
2023-09-23 11:51:37 +08:00
|
|
|
switch (osVersion.dwPlatformId)
|
|
|
|
|
{
|
|
|
|
|
case VER_PLATFORM_WIN32s:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemName, "WIN32s");
|
2023-09-23 11:51:37 +08:00
|
|
|
break;
|
|
|
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemName, "WIN32_WINDOWS");
|
2023-09-23 11:51:37 +08:00
|
|
|
break;
|
|
|
|
|
case VER_PLATFORM_WIN32_NT:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemName, "WIN32_NT");
|
2023-09-23 11:51:37 +08:00
|
|
|
break;
|
|
|
|
|
}
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-08 00:02:00 +08:00
|
|
|
static void getSystemArchitectureAndPageSize(FFPlatform* platform)
|
2023-01-15 15:57:26 +01:00
|
|
|
{
|
2023-11-08 00:02:00 +08:00
|
|
|
SYSTEM_INFO sysInfo;
|
2023-01-15 15:57:26 +01:00
|
|
|
GetNativeSystemInfo(&sysInfo);
|
|
|
|
|
|
|
|
|
|
switch(sysInfo.wProcessorArchitecture)
|
|
|
|
|
{
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "x86_64");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_IA64:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "ia64");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
2024-02-15 20:29:34 +08:00
|
|
|
switch (sysInfo.wProcessorLevel)
|
|
|
|
|
{
|
|
|
|
|
case 4:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "i486");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
|
|
|
|
case 5:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "i586");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
|
|
|
|
case 6:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "i686");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
|
|
|
|
default:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "i386");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
|
|
|
|
}
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_ARM64:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "aarch64");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_ARM:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "arm");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_PPC:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "ppc");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_MIPS:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "mips");
|
2023-01-15 15:57:26 +01:00
|
|
|
break;
|
2024-02-15 20:29:34 +08:00
|
|
|
case PROCESSOR_ARCHITECTURE_ALPHA:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "alpha");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
|
|
|
|
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
2024-02-15 20:29:57 +08:00
|
|
|
ffStrbufSetStatic(&platform->systemArchitecture, "alpha64");
|
2024-02-15 20:29:34 +08:00
|
|
|
break;
|
2023-01-15 15:57:26 +01:00
|
|
|
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-11-08 00:02:00 +08:00
|
|
|
|
|
|
|
|
platform->pageSize = sysInfo.dwPageSize;
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-15 16:06:50 +01:00
|
|
|
void ffPlatformInitImpl(FFPlatform* platform)
|
2023-01-15 15:57:26 +01:00
|
|
|
{
|
2023-08-24 13:47:20 +08:00
|
|
|
getExePath(platform);
|
2023-01-15 15:57:26 +01:00
|
|
|
getHomeDir(platform);
|
|
|
|
|
getCacheDir(platform);
|
|
|
|
|
getConfigDirs(platform);
|
|
|
|
|
getDataDirs(platform);
|
|
|
|
|
|
|
|
|
|
getUserName(platform);
|
|
|
|
|
getHostName(platform);
|
2023-09-18 13:52:25 +08:00
|
|
|
getUserShell(platform);
|
2023-01-15 15:57:26 +01:00
|
|
|
|
|
|
|
|
getSystemReleaseAndVersion(platform);
|
2023-11-08 00:02:00 +08:00
|
|
|
getSystemArchitectureAndPageSize(platform);
|
2023-01-15 15:57:26 +01:00
|
|
|
}
|