mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-22 07:14:15 +08:00
Feature: Support customizing client name and install directory
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user