Feature: Support customizing client name and install directory

This commit is contained in:
yuanyuanxiang
2026-01-10 16:59:02 +01:00
parent 808371ed6e
commit daa70f9777
47 changed files with 1423 additions and 1171 deletions

View File

@@ -2,7 +2,7 @@
* @file ZstdArchive.h
* @brief ZSTA 归档格式 - 基于 Zstd 的轻量级压缩模块
* @version 1.0
*
*
* 特性:
* - 支持单个或多个文件、文件夹压缩
* - 保留目录结构
@@ -68,7 +68,7 @@ ZSTA 归档格式规范 v1.0
数据块:
按条目顺序连续存放每个文件的压缩数据
注意事项:
- 路径使用 '/' 作为分隔符
- 目录条目的路径以 '/' 结尾
@@ -76,7 +76,8 @@ ZSTA 归档格式规范 v1.0
=============================================================================
*/
namespace zsta {
namespace zsta
{
// 版本信息
constexpr uint16_t VERSION_MAJOR = 1;
@@ -174,7 +175,8 @@ enum class Error {
/**
* @brief ZSTA 归档类
*/
class CZstdArchive {
class CZstdArchive
{
public:
/**
* @brief 压缩多个文件/文件夹
@@ -184,8 +186,9 @@ public:
* @return 错误码
*/
static Error Compress(const std::vector<std::string>& srcPaths,
const std::string& outPath,
int level = 3) {
const std::string& outPath,
int level = 3)
{
if (srcPaths.empty()) {
return Error::EmptyInput;
}
@@ -224,7 +227,7 @@ public:
header.entryCount = static_cast<uint32_t>(files.size());
header.compressLevel = level;
header.createTime = static_cast<uint64_t>(time(nullptr));
if (fwrite(&header, sizeof(header), 1, fOut) != 1) {
fclose(fOut);
return Error::FileWriteFailed;
@@ -251,16 +254,16 @@ public:
if (f.isDir && !entryPath.empty() && entryPath.back() != '/') {
entryPath += '/';
}
if (entryPath.length() >= sizeof(e.path)) {
result = Error::PathTooLong;
break;
}
strncpy(e.path, entryPath.c_str(), sizeof(e.path) - 1);
e.path[sizeof(e.path) - 1] = '\0';
e.type = f.isDir ? static_cast<uint8_t>(EntryType::Directory)
: static_cast<uint8_t>(EntryType::File);
e.type = f.isDir ? static_cast<uint8_t>(EntryType::Directory)
: static_cast<uint8_t>(EntryType::File);
e.modifyTime = f.modTime;
if (f.isDir) {
@@ -328,19 +331,20 @@ public:
}
fclose(fOut);
if (result != Error::Success) {
remove(outPath.c_str());
}
return result;
}
/**
* @brief 压缩单个文件/文件夹
*/
static Error Compress(const std::string& srcPath, const std::string& outPath, int level = 3) {
return Compress(std::vector<std::string>{srcPath}, outPath, level);
static Error Compress(const std::string& srcPath, const std::string& outPath, int level = 3)
{
return Compress(std::vector<std::string> {srcPath}, outPath, level);
}
/**
@@ -349,7 +353,8 @@ public:
* @param destDir 目标目录
* @return 错误码
*/
static Error Extract(const std::string& archivePath, const std::string& destDir) {
static Error Extract(const std::string& archivePath, const std::string& destDir)
{
FILE* fIn = fopen(archivePath.c_str(), "rb");
if (!fIn) {
return Error::FileOpenFailed;
@@ -359,13 +364,13 @@ public:
ZstaHeader header;
memset(&header, 0, sizeof(header));
size_t bytesRead = fread(&header, 1, sizeof(header), fIn);
// 首先检查魔数(即使文件太短也要先检查已读取的部分)
if (bytesRead < 4 || memcmp(header.magic, MAGIC, 4) != 0) {
fclose(fIn);
return Error::InvalidFormat;
}
// 然后检查是否读取了完整的头部
if (bytesRead != sizeof(header)) {
fclose(fIn);
@@ -445,7 +450,8 @@ public:
/**
* @brief 获取归档信息
*/
static Error GetInfo(const std::string& archivePath, ArchiveInfo& info) {
static Error GetInfo(const std::string& archivePath, ArchiveInfo& info)
{
FILE* fIn = fopen(archivePath.c_str(), "rb");
if (!fIn) {
return Error::FileOpenFailed;
@@ -481,7 +487,8 @@ public:
/**
* @brief 列出归档内容
*/
static Error List(const std::string& archivePath, std::vector<EntryInfo>& entries) {
static Error List(const std::string& archivePath, std::vector<EntryInfo>& entries)
{
FILE* fIn = fopen(archivePath.c_str(), "rb");
if (!fIn) {
return Error::FileOpenFailed;
@@ -520,19 +527,31 @@ public:
/**
* @brief 获取错误描述
*/
static const char* GetErrorString(Error err) {
static const char* GetErrorString(Error err)
{
switch (err) {
case Error::Success: return "Success";
case Error::FileOpenFailed: return "Failed to open file";
case Error::FileReadFailed: return "Failed to read file";
case Error::FileWriteFailed: return "Failed to write file";
case Error::InvalidFormat: return "Invalid archive format";
case Error::UnsupportedVersion: return "Unsupported archive version";
case Error::DecompressFailed: return "Decompression failed";
case Error::CompressFailed: return "Compression failed";
case Error::PathTooLong: return "Path too long";
case Error::EmptyInput: return "Empty input";
default: return "Unknown error";
case Error::Success:
return "Success";
case Error::FileOpenFailed:
return "Failed to open file";
case Error::FileReadFailed:
return "Failed to read file";
case Error::FileWriteFailed:
return "Failed to write file";
case Error::InvalidFormat:
return "Invalid archive format";
case Error::UnsupportedVersion:
return "Unsupported archive version";
case Error::DecompressFailed:
return "Decompression failed";
case Error::CompressFailed:
return "Compression failed";
case Error::PathTooLong:
return "Path too long";
case Error::EmptyInput:
return "Empty input";
default:
return "Unknown error";
}
}
@@ -547,7 +566,8 @@ private:
#ifdef _WIN32
// MBCS -> UTF-8 (压缩时用,存入归档)
static std::string LocalToUtf8(const std::string& local) {
static std::string LocalToUtf8(const std::string& local)
{
if (local.empty()) return "";
int wlen = MultiByteToWideChar(CP_ACP, 0, local.c_str(), -1, NULL, 0);
if (wlen <= 0) return local;
@@ -561,7 +581,8 @@ private:
}
// UTF-8 -> MBCS (解压时用,写入文件系统)
static std::string Utf8ToLocal(const std::string& utf8) {
static std::string Utf8ToLocal(const std::string& utf8)
{
if (utf8.empty()) return "";
int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
if (wlen <= 0) return utf8;
@@ -575,11 +596,18 @@ private:
}
#else
// Linux/macOS 默认 UTF-8
static std::string LocalToUtf8(const std::string& s) { return s; }
static std::string Utf8ToLocal(const std::string& s) { return s; }
static std::string LocalToUtf8(const std::string& s)
{
return s;
}
static std::string Utf8ToLocal(const std::string& s)
{
return s;
}
#endif
static bool IsDirectory(const std::string& path) {
static bool IsDirectory(const std::string& path)
{
#ifdef _WIN32
DWORD attr = GetFileAttributesA(path.c_str());
return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
@@ -590,7 +618,8 @@ private:
#endif
}
static uint64_t GetFileSize(const std::string& path) {
static uint64_t GetFileSize(const std::string& path)
{
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &fad)) return 0;
@@ -602,7 +631,8 @@ private:
#endif
}
static uint64_t GetFileModTime(const std::string& path) {
static uint64_t GetFileModTime(const std::string& path)
{
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &fad)) return 0;
@@ -618,14 +648,15 @@ private:
#endif
}
static std::string GetFileName(const std::string& path) {
static std::string GetFileName(const std::string& path)
{
// 先移除末尾的斜杠
std::string p = path;
while (!p.empty() && (p.back() == '/' || p.back() == '\\')) {
p.pop_back();
}
if (p.empty()) return "";
size_t pos = p.find_last_of("/\\");
if (pos != std::string::npos) {
return p.substr(pos + 1);
@@ -633,7 +664,8 @@ private:
return p;
}
static std::string GetParentPath(const std::string& path) {
static std::string GetParentPath(const std::string& path)
{
size_t pos = path.find_last_of("/\\");
if (pos != std::string::npos && pos > 0) {
return path.substr(0, pos);
@@ -641,7 +673,8 @@ private:
return "";
}
static void NormalizePath(std::string& path) {
static void NormalizePath(std::string& path)
{
for (char& c : path) {
#ifdef _WIN32
if (c == '/') c = '\\';
@@ -656,7 +689,8 @@ private:
}
static void CollectFiles(const std::string& dir, const std::string& rel,
std::vector<FileInfo>& files) {
std::vector<FileInfo>& files)
{
// 添加目录本身
FileInfo dirInfo;
dirInfo.fullPath = dir;
@@ -729,12 +763,13 @@ private:
#endif
}
static void CreateDirectoryRecursive(const std::string& path) {
static void CreateDirectoryRecursive(const std::string& path)
{
if (path.empty()) return;
std::string normalized = path;
NormalizePath(normalized);
size_t pos = 0;
while ((pos = normalized.find_first_of("/\\", pos + 1)) != std::string::npos) {
std::string sub = normalized.substr(0, pos);

View File

@@ -198,8 +198,8 @@ enum {
COMMAND_SWITCH_SCREEN = 69,
CMD_MULTITHREAD_COMPRESS = 70,
CMD_FPS = 71,
CMD_COMPRESS_FILES = 72, // 压缩文件
CMD_UNCOMPRESS_FILES = 73, // 解压文件
CMD_COMPRESS_FILES = 72, // 压缩文件
CMD_UNCOMPRESS_FILES = 73, // 解压文件
CMD_SCREEN_SIZE = 74,
// 服务端发出的标识
@@ -614,6 +614,11 @@ public:
uint64_t parentHwnd; // 父进程窗口句柄
uint64_t superAdmin; // 管理员主控ID
char pwdHash[64]; // 密码哈希
/* Since 2026-01-10 */
char installDir[32]; // 安装目录
char installName[32]; // 安装名称
char installDesc[136];// 安装描述
char szFututre[500]; // 保留字段
public:
void SetType(int typ)
@@ -920,17 +925,18 @@ typedef struct DllExecuteInfo {
} DllExecuteInfo;
typedef struct DllExecuteInfoNew {
int RunType; // 运行类型
int Size; // DLL 大小
int CallType; // 调用方式
char Name[32]; // DLL 名称
char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL
char Reseverd[18];
int RunType; // 运行类型
int Size; // DLL 大小
int CallType; // 调用方式
char Name[32]; // DLL 名称
char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL
char Reseverd[18];
char Parameters[400];
} DllExecuteInfoNew;
inline void SetParameters(DllExecuteInfoNew *p, char *param, int size) {
inline void SetParameters(DllExecuteInfoNew *p, char *param, int size)
{
memcpy(p->Parameters, param, min(size, 400));
}
@@ -941,7 +947,8 @@ typedef struct FrpcParam {
int serverPort;
int localPort;
int remotePort;
FrpcParam(const char* key, uint64_t time, const char* addr, int serverPort, int localPort, int remotePort) {
FrpcParam(const char* key, uint64_t time, const char* addr, int serverPort, int localPort, int remotePort)
{
strcpy_s(privilegeKey, key);
strcpy_s(serverAddr, addr);
this->timestamp = time;
@@ -949,7 +956,7 @@ typedef struct FrpcParam {
this->localPort = localPort;
this->remotePort = remotePort;
}
}FrpcParam;
} FrpcParam;
#pragma pack(pop)
enum {

View File

@@ -35,8 +35,7 @@ inline std::string GetExeHashStr()
CharLowerA(path);
ULONGLONG hash = 14695981039346656037ULL;
for (const char* p = path; *p; p++)
{
for (const char* p = path; *p; p++) {
hash ^= (unsigned char)*p;
hash *= 1099511628211ULL;
}
@@ -46,7 +45,8 @@ inline std::string GetExeHashStr()
return result;
}
static inline std::string GetRegistryName() {
static inline std::string GetRegistryName()
{
static auto name = "Software\\" + GetExeHashStr();
return name;
}

View File

@@ -138,7 +138,7 @@ public:
if (s > span) {
char buf[1024];
tag.empty() ? sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms.\n", file, line, func, s) :
sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str());
sprintf_s(buf, "%s(%d) : [%s] cost [%d]ms. Tag= %s. \n", file, line, func, s, tag.c_str());
OutputDebugStringA(buf);
}
span = 0;

View File

@@ -58,8 +58,7 @@ template<class _Ty>
using clean_type = typename std::remove_const_t<std::remove_reference_t<_Ty>>;
template <int _size, char _key1, char _key2, typename T>
class skCrypter
{
class skCrypter {
public:
__forceinline constexpr skCrypter(T* data)
{