feat(hardening): 内嵌产品配置 + 系统级状态 + 全量 i18n + 依赖治理 + 资料清理
update-client-hardening 四工作流合入(构建/静态检查已过): - 配置:不可变产品策略经 UpdateClientResources.cmake 归一化校验后 内嵌 qrc(URL/相对路径/主程序必须落 install_root/版本/UUID 格式, CMake override 写入前复验);可变机器状态迁系统级原生存储; 运行目录不再落可编辑 app_config.json。 - i18n:生产源全英文(no-Han 检查 41/41),中文进 translations/ zh_CN 目录;翻译加载收敛 Common/TranslationHelper 唯一入口; Bootstrap 补资源文件。 - 依赖:Qt/OpenSSL/架构/Perl 机器路径改 imported targets + UpdateClientDependencies.cmake,3rdparty 由父工程契约供给。 - 清理:旧 README/SDK README/3 个重复 PowerShell 打包脚本/PDF 提取 文本删除,canonical README + 5 份结构化英文文档替代;Launcher requireAdministrator manifest;统一 MSVC /utf-8 删运行时编码设置。
This commit is contained in:
+24
-6
@@ -1,5 +1,6 @@
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include "resource.h"
|
||||
#include <filesystem>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
@@ -10,6 +11,21 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static std::wstring loadLocalizedString(unsigned int id)
|
||||
{
|
||||
const wchar_t* value = nullptr;
|
||||
const int length = LoadStringW(GetModuleHandleW(nullptr), id,
|
||||
reinterpret_cast<LPWSTR>(&value), 0);
|
||||
return length > 0 ? std::wstring(value, static_cast<size_t>(length)) : std::wstring();
|
||||
}
|
||||
|
||||
static void showBootstrapError(unsigned int messageId)
|
||||
{
|
||||
const std::wstring message = loadLocalizedString(messageId);
|
||||
const std::wstring title = loadLocalizedString(IDS_BOOTSTRAP_ERROR_TITLE);
|
||||
MessageBoxW(nullptr, message.c_str(), title.c_str(), MB_ICONERROR);
|
||||
}
|
||||
|
||||
static std::wstring quote(const std::wstring& value)
|
||||
{
|
||||
std::wstring result = L"\"";
|
||||
@@ -115,7 +131,7 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
|
||||
int argc = 0;
|
||||
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
if (!argv || argc < 11) {
|
||||
MessageBoxW(nullptr, L"Bootstrap 参数不完整。", L"更新接管失败", MB_ICONERROR);
|
||||
showBootstrapError(IDS_BOOTSTRAP_ARGUMENTS_INCOMPLETE);
|
||||
if (argv) LocalFree(argv);
|
||||
return 2;
|
||||
}
|
||||
@@ -142,12 +158,12 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
|
||||
while (std::getline(input, line)) {
|
||||
if (!line.empty() && line.back() == '\r') line.pop_back();
|
||||
if (line.size() < 3 || line[1] != '\t' || (line[0] != 'C' && line[0] != 'D')) {
|
||||
MessageBoxW(nullptr, L"更新计划操作格式无效。", L"更新接管失败", MB_ICONERROR);
|
||||
showBootstrapError(IDS_BOOTSTRAP_INVALID_PLAN_OPERATION);
|
||||
return 3;
|
||||
}
|
||||
const fs::path relative(fromUtf8(line.substr(2)));
|
||||
if (!safeRelative(relative)) {
|
||||
MessageBoxW(nullptr, L"更新计划包含不安全路径。", L"更新接管失败", MB_ICONERROR);
|
||||
showBootstrapError(IDS_BOOTSTRAP_UNSAFE_PLAN_PATH);
|
||||
return 3;
|
||||
}
|
||||
items.push_back({static_cast<wchar_t>(line[0]), relative});
|
||||
@@ -182,9 +198,11 @@ int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
|
||||
|
||||
const std::wstring result = success ? L"success" : (rolledBack ? L"rolledback" : L"rollback-failed");
|
||||
if (!launchUpdater(updater, updateArgs, result)) {
|
||||
std::wstring message = L"无法重新启动 Updater.exe。";
|
||||
if (!failedPath.empty()) message += L"\n失败文件:" + failedPath.wstring();
|
||||
MessageBoxW(nullptr, message.c_str(), L"更新接管失败", MB_ICONERROR);
|
||||
std::wstring message = loadLocalizedString(IDS_BOOTSTRAP_RESTART_UPDATER_FAILED);
|
||||
if (!failedPath.empty())
|
||||
message += L"\n" + loadLocalizedString(IDS_BOOTSTRAP_FAILED_FILE_PREFIX) + failedPath.wstring();
|
||||
const std::wstring title = loadLocalizedString(IDS_BOOTSTRAP_ERROR_TITLE);
|
||||
MessageBoxW(nullptr, message.c_str(), title.c_str(), MB_ICONERROR);
|
||||
return 4;
|
||||
}
|
||||
return (success || rolledBack) ? 0 : 5;
|
||||
|
||||
Reference in New Issue
Block a user