mirror of
https://github.com/LHY0125/PathEditor.git
synced 2026-05-10 02:09:46 +08:00
3bc2f00cb1
- 在备份失败时显示具体原因(如无法获取AppData路径、创建备份目录失败等) - 改进备份函数的错误处理,添加详细的日志记录 - 备份失败时允许用户选择是否继续保存操作 - 修复备份目录创建失败时的错误码返回 - 添加备份过程的详细文档说明
170 lines
4.9 KiB
C
170 lines
4.9 KiB
C
#include "utils/os_env.h"
|
|
#include "utils/string_ext.h"
|
|
#include "utils/logger.h"
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <direct.h>
|
|
#include <shlobj.h>
|
|
|
|
// 检查管理员权限
|
|
int check_admin(void)
|
|
{
|
|
HKEY hKey;
|
|
LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_WRITE, &hKey);
|
|
if (result == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// 内部:检查路径是否存在
|
|
static int path_exists(const char *path)
|
|
{
|
|
// 如果包含 %,说明是变量,无法直接检查存在性,默认视为有效
|
|
if (strchr(path, '%'))
|
|
return 1;
|
|
|
|
wchar_t *wpath = utf8_to_wide(path);
|
|
if (!wpath)
|
|
return 0;
|
|
|
|
DWORD attr = GetFileAttributesW(wpath);
|
|
free(wpath);
|
|
|
|
if (attr == INVALID_FILE_ATTRIBUTES)
|
|
return 0;
|
|
return (attr & FILE_ATTRIBUTE_DIRECTORY); // 必须是目录
|
|
}
|
|
|
|
// 检查路径是否存在(公开给外部使用)
|
|
int is_path_valid(const char *path)
|
|
{
|
|
return path_exists(path);
|
|
}
|
|
|
|
// 备份注册表
|
|
// 备份到 %APPDATA%/PathEditor/backups/ 目录下
|
|
// 返回值:
|
|
// ERR_OK - 备份成功(系统和用户 PATH 都已备份)
|
|
// ERR_FAILED - AppData 路径获取失败
|
|
// ERR_FILE_NOT_FOUND - 备份文件创建失败
|
|
// ERR_REGISTRY_FAILED - 系统和用户 PATH 都读取失败
|
|
ErrorCode backup_registry(void)
|
|
{
|
|
// 获取 AppData 路径
|
|
wchar_t appdata_path[MAX_PATH];
|
|
if (SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path) != S_OK)
|
|
{
|
|
log_error("Failed to get AppData path");
|
|
return ERR_FAILED;
|
|
}
|
|
|
|
// 创建备份目录(递归创建中间目录)
|
|
wchar_t backup_dir[MAX_PATH];
|
|
swprintf(backup_dir, MAX_PATH, L"%s\\PathEditor\\backups", appdata_path);
|
|
if (SHCreateDirectoryExW(NULL, backup_dir, NULL) != ERROR_SUCCESS)
|
|
{
|
|
log_error("Failed to create backup directory: %ls", backup_dir);
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
// 生成时间戳
|
|
time_t t = time(NULL);
|
|
struct tm tm_info;
|
|
localtime_s(&tm_info, &t);
|
|
wchar_t timestamp[64];
|
|
wcsftime(timestamp, sizeof(timestamp) / sizeof(timestamp[0]), L"%Y%m%d_%H%M%S", &tm_info);
|
|
|
|
// 构造备份文件名
|
|
wchar_t backup_file[MAX_PATH];
|
|
swprintf(backup_file, MAX_PATH, L"%s\\path_backup_%s.txt", backup_dir, timestamp);
|
|
|
|
// 打开文件
|
|
FILE *fp = _wfopen(backup_file, L"w, ccs=UTF-8");
|
|
if (!fp)
|
|
{
|
|
log_error("Failed to create backup file: %ls", backup_file);
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
// 备份系统 PATH
|
|
HKEY hKey;
|
|
int sys_ok = 0;
|
|
int user_ok = 0;
|
|
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD type, size;
|
|
if (RegQueryValueExW(hKey, L"Path", NULL, &type, NULL, &size) == ERROR_SUCCESS)
|
|
{
|
|
wchar_t *buffer = (wchar_t *)malloc(size + 2);
|
|
if (buffer)
|
|
{
|
|
memset(buffer, 0, size + 2);
|
|
if (RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS)
|
|
{
|
|
fwprintf(fp, L"# System PATH Backup\n");
|
|
fwprintf(fp, L"%s\n\n", buffer);
|
|
sys_ok = 1;
|
|
}
|
|
free(buffer);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
log_warn("Failed to open system PATH registry key");
|
|
}
|
|
|
|
// 备份用户 PATH
|
|
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
|
L"Environment",
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD type, size;
|
|
if (RegQueryValueExW(hKey, L"Path", NULL, &type, NULL, &size) == ERROR_SUCCESS)
|
|
{
|
|
wchar_t *buffer = (wchar_t *)malloc(size + 2);
|
|
if (buffer)
|
|
{
|
|
memset(buffer, 0, size + 2);
|
|
if (RegQueryValueExW(hKey, L"Path", NULL, &type, (LPBYTE)buffer, &size) == ERROR_SUCCESS)
|
|
{
|
|
fwprintf(fp, L"# User PATH Backup\n");
|
|
fwprintf(fp, L"%s\n", buffer);
|
|
user_ok = 1;
|
|
}
|
|
free(buffer);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
log_warn("Failed to open user PATH registry key");
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
// 判断备份结果
|
|
if (!sys_ok && !user_ok)
|
|
{
|
|
log_error("Backup failed: both system and user PATH read failed");
|
|
return ERR_REGISTRY_FAILED;
|
|
}
|
|
|
|
if (!sys_ok)
|
|
log_warn("Backup partial: system PATH read failed, only user PATH backed up");
|
|
if (!user_ok)
|
|
log_warn("Backup partial: user PATH read failed, only system PATH backed up");
|
|
|
|
log_info("Backup completed: sys=%d, user=%d, file=%ls", sys_ok, user_ok, backup_file);
|
|
return ERR_OK;
|
|
} |