Files
skeet_loader/skeet_loader/main/Backend/Steam/Steam.cpp
T
2026-06-08 15:51:52 +08:00

244 lines
6.1 KiB
C++

#include "Steam.h"
#include <windows.h>
#include <tlhelp32.h>
#include <cstdio>
#include "../../Menu/Menu.h"
// 嵌入的 Steam 覆盖层文件数据(定义在各 .h 中)
extern unsigned int gameoverlayui_exe_len;
extern unsigned char gameoverlayui_exe[];
extern unsigned int gameoverlayui64_exe_len;
extern unsigned char gameoverlayui64_exe[];
extern unsigned int GameOverlayRenderer_dll_len;
extern unsigned char GameOverlayRenderer_dll[];
extern unsigned int GameOverlayRenderer64_dll_len;
extern unsigned char GameOverlayRenderer64_dll[];
// 单例
Steam* Steam::Get()
{
static Steam instance;
return &instance;
}
Steam::Steam() = default;
Steam::~Steam() = default;
const std::string& Steam::GetSteamPath() const {
// 每次调用都从注册表查询 Steam 安装路径
HKEY hKey;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, KEY_READ | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) {
char path[MAX_PATH];
DWORD size = sizeof(path);
if (RegQueryValueExA(hKey, "InstallPath", nullptr, nullptr,
reinterpret_cast<BYTE*>(path), &size) == ERROR_SUCCESS)
{
m_SteamPath = path;
RegCloseKey(hKey);
printf("[Steam] > install path: %s\n", m_SteamPath.c_str());
return m_SteamPath;
}
RegCloseKey(hKey);
}
// 回退:当前用户注册表
if (RegOpenKeyExA(HKEY_CURRENT_USER,
"SOFTWARE\\Valve\\Steam", 0,
KEY_READ | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS)
{
char path[MAX_PATH];
DWORD size = sizeof(path);
if (RegQueryValueExA(hKey, "SteamPath", nullptr, nullptr,
reinterpret_cast<BYTE*>(path), &size) == ERROR_SUCCESS)
{
m_SteamPath = path;
RegCloseKey(hKey);
printf("[Steam] > install path: %s\n", m_SteamPath.c_str());
return m_SteamPath;
}
RegCloseKey(hKey);
}
m_SteamPath.clear();
printf("[Steam] > warn: could not find steam install path\n");
return m_SteamPath;
}
bool Steam::IsProcessRunning(const wchar_t* exeName) const {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(pe32);
bool found = false;
if (Process32FirstW(hSnapshot, &pe32))
{
do
{
if (_wcsicmp(pe32.szExeFile, exeName) == 0)
{
found = true;
break;
}
} while (Process32NextW(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
return found;
}
bool Steam::TerminateProcessByName(const wchar_t* exeName) const {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(pe32);
bool killed = false;
if (Process32FirstW(hSnapshot, &pe32))
{
do
{
if (_wcsicmp(pe32.szExeFile, exeName) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
if (hProcess)
{
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
killed = true;
}
}
} while (Process32NextW(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
return killed;
}
bool Steam::IsSteamRunning() {
return IsProcessRunning(L"steam.exe");
}
bool Steam::StartSteam() {
const std::string& steamPath = GetSteamPath();
if (steamPath.empty())
{
printf("[Steam] > err: steam path unknown, cannot start\n");
return false;
}
std::string exePath = steamPath + "\\steam.exe";
HINSTANCE result = ShellExecuteA(
nullptr, "open", exePath.c_str(), nullptr, nullptr, SW_SHOW
);
if (reinterpret_cast<INT_PTR>(result) > 32)
{
printf("[Steam] > started: %s\n", exePath.c_str());
return true;
}
printf("[Steam] > err: failed to start (code %d)\n",
static_cast<int>(reinterpret_cast<INT_PTR>(result)));
return false;
}
bool Steam::KillSteam() {
auto Log = Menu::Get();
if (!IsSteamRunning())
{
printf("[Steam] > steam not running\n");
Log->AddLog("[Steam] > steam not running");
return false;
}
if (TerminateProcessByName(L"steam.exe"))
{
printf("[Steam] > steam killed\n");
Log->AddLog("[Steam] > steam killed");
return true;
}
printf("[Steam] > err: failed to kill steam\n");
Log->AddLog("[Steam] > err: failed to kill steam");
return false;
}
// ─── 写入嵌入文件到磁盘的辅助函数 ────────────────────────────
static bool WriteEmbeddedFile(const std::string& dir, const char* name, const file& f)
{
std::string fullPath = dir + "\\" + name;
HANDLE hFile = CreateFileA(
fullPath.c_str(),
GENERIC_WRITE,
0,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("[Steam] > err: cannot create file %s (0x%lx)\n", fullPath.c_str(), GetLastError());
return false;
}
DWORD written = 0;
const BOOL ok = WriteFile(hFile, f.file, f.len, &written, nullptr);
CloseHandle(hFile);
if (!ok || written != f.len)
{
printf("[Steam] > err: write failed for %s (wrote %lu/%u)\n", fullPath.c_str(), written, f.len);
return false;
}
printf("[Steam] > replaced: %s (%u bytes)\n", fullPath.c_str(), f.len);
return true;
}
// ─── 替换 Steam 覆盖层文件 ──────────────────────────────────
bool Steam::ReplaceOverlayFiles()
{
auto Log = Menu::Get();
const std::string& steamPath = GetSteamPath();
if (steamPath.empty())
{
printf("[Steam] > err: steam path unknown, cannot replace overlay files\n");
Log->AddLog("[Steam] > err: steam path unknown, cannot replace overlay files");
return false;
}
printf("[Steam] > replacing overlay files in: %s\n", steamPath.c_str());
bool allOk = true;
allOk &= WriteEmbeddedFile(steamPath, "gameoverlayui.exe", gameoverlayui());
allOk &= WriteEmbeddedFile(steamPath, "GameOverlayRenderer.dll", GameOverlayRenderer());
allOk &= WriteEmbeddedFile(steamPath, "gameoverlayui64.exe", gameoverlayui64());
allOk &= WriteEmbeddedFile(steamPath, "GameOverlayRenderer64.dll", GameOverlayRenderer64());
if (allOk) {
printf("[Steam] > all overlay files replaced successfully\n");
Log->AddLog("[Steam] > all overlay files replaced successfully");
}
else {
printf("[Steam] > warn: some overlay files failed to replace\n");
Log->AddLog("[Steam] > warn: some overlay files failed to replace");
}
return allOk;
}