You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
9.7 KiB
C++

#include "stdafx.h"
#include "../FormaConversion/DFDConversion.h"
#include "FileUtility.h"
// 不能修改,否则打开文件会有问题
static const char KEV_XORKEY[] = "VersionRamanujan";
/**
* @brief 异或加密
*
* @param data
* @param key
*/
void XorEncrypt(LPTSTR lpData, DWORD len, LPCTSTR lpKey) {
size_t key_len = strlen(lpKey);
for (size_t i = 0; i < len; i++) {
lpData[i] ^= lpKey[i % key_len];
}
}
/**
* @brief 异或加密指定文件.
*
* @param lpFilePath
* @return
*/
BOOL XorEncryptFile(LPCTSTR lpFilePath)
{
HANDLE hDstFile = CreateFile(lpFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDstFile == INVALID_HANDLE_VALUE) {
TRACE("Failed to open destination file, error code: %d\n", GetLastError());
return FALSE;
}
DWORD dwFileSizeHigh = 0;
DWORD dwFileSizeLow = GetFileSize(hDstFile, &dwFileSizeHigh);
HANDLE hMapping = CreateFileMapping(hDstFile, NULL, PAGE_READWRITE, dwFileSizeHigh, dwFileSizeLow, NULL);
if (hMapping == NULL) {
TRACE("Failed to create file mapping, error code: %d\n", GetLastError());
CloseHandle(hDstFile);
return FALSE;
}
LPVOID lpMapping = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpMapping == NULL) {
TRACE("Failed to map view of file, error code: %d\n", GetLastError());
CloseHandle(hMapping);
CloseHandle(hDstFile);
return FALSE;
}
LARGE_INTEGER large_integer;
GetFileSizeEx(hDstFile, &large_integer);
XorEncrypt((LPTSTR)lpMapping, large_integer.QuadPart, KEV_XORKEY);
UnmapViewOfFile(lpMapping);
CloseHandle(hMapping);
CloseHandle(hDstFile);
return true;
}
/**
* @brief 创建临时加密文件.
*
* @param lpSrcFilePath 指定的源文件
* @param lpDstFilePath 指定的临时文件
* @return
*/
BOOL XorEncryptFile(LPCTSTR lpSrcFilePath, LPCTSTR lpDstFilePath)
{
bool ret = false;
if (!CheckAndCreateDirectory(GetTempDirectory()))
{
return false;
}
if (lpDstFilePath != NULL && strcmp(lpSrcFilePath, lpDstFilePath) != 0)
{
ret = CopyLargeFileByMapping(lpSrcFilePath, lpDstFilePath);
if (!ret)
{
return false;
}
ret = XorEncryptFile(lpDstFilePath);
}
else {
ret = XorEncryptFile(lpSrcFilePath);
}
return ret;
}
/**
* @brief 文件映射内存拷贝
*
* @param lpSrcFilePath
* @param lpDstFilePath
* @return
*/
BOOL CopyLargeFileByMapping(LPCTSTR lpSrcFilePath, LPCTSTR lpDstFilePath)
{
HANDLE hSrcFile = CreateFile(lpSrcFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hSrcFile == INVALID_HANDLE_VALUE) {
TRACE("Failed to open source file, error code: %d\n", GetLastError());
return FALSE;
}
DWORD dwFileSizeHigh = 0, dwFileSizeLow = GetFileSize(hSrcFile, &dwFileSizeHigh);
if (dwFileSizeLow == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) {
TRACE("Failed to get the size of source file, error code: %d\n", GetLastError());
CloseHandle(hSrcFile);
return FALSE;
}
HANDLE hDstFile = CreateFile(lpDstFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDstFile == INVALID_HANDLE_VALUE) {
TRACE("Failed to create destination file, error code: %d\n", GetLastError());
CloseHandle(hSrcFile);
return FALSE;
}
HANDLE hMapping = CreateFileMapping(hSrcFile, NULL, PAGE_READONLY, dwFileSizeHigh, dwFileSizeLow, NULL);
if (hMapping == NULL) {
TRACE("Failed to create file mapping, error code: %d\n", GetLastError());
CloseHandle(hDstFile);
CloseHandle(hSrcFile);
return FALSE;
}
LPVOID lpMapping = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (lpMapping == NULL) {
TRACE("Failed to map view of file, error code: %d\n", GetLastError());
CloseHandle(hMapping);
CloseHandle(hDstFile);
CloseHandle(hSrcFile);
return FALSE;
}
DWORD dwBytesWritten = 0;
if (!WriteFile(hDstFile, lpMapping, dwFileSizeLow, &dwBytesWritten, NULL) || dwBytesWritten != dwFileSizeLow) {
TRACE("Failed to write to destination file, error code: %d\n", GetLastError());
UnmapViewOfFile(lpMapping);
CloseHandle(hMapping);
CloseHandle(hDstFile);
CloseHandle(hSrcFile);
return FALSE;
}
UnmapViewOfFile(lpMapping);
CloseHandle(hMapping);
CloseHandle(hDstFile);
CloseHandle(hSrcFile);
TRACE("Successfully copied the file!\n");
return TRUE;
}
/**
* @brief 判断是否是UNICODE文件.
*
* @param filename
* @return
*/
bool IsUnicodeTextFile(const char *filename) {
HANDLE fileHandle = CreateFile(
filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
perror("Failed to open file");
return false;
}
DWORD fileSize = GetFileSize(fileHandle, NULL);
if (fileSize == INVALID_FILE_SIZE) {
CloseHandle(fileHandle);
perror("Failed to get file size");
return false;
}
HANDLE mappingHandle = CreateFileMapping(
fileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
if (mappingHandle == NULL) {
CloseHandle(fileHandle);
perror("Failed to create file mapping");
return false;
}
LPVOID fileBuffer = MapViewOfFile(mappingHandle, FILE_MAP_READ, 0, 0, fileSize);
if (fileBuffer == NULL) {
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
perror("Failed to map view of file");
return false;
}
bool isText = IsTextUnicode(fileBuffer, fileSize, NULL);
UnmapViewOfFile(fileBuffer);
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
return isText;
}
/**
* @brief 是否是二进制文件.
*
* @param file
* @return
*/
bool IsBinaryFile(CString filePath)
{
FILE* file = fopen(filePath, "rb");
if (file == NULL)
{
return false; // 打开文件失败,默认认为不是二进制文件
}
int isBinary = false;
unsigned char buffer[512];
size_t bytesRead = fread(buffer, 1, sizeof(buffer), file);
if (bytesRead > 0)
{
for (size_t i = 0; i < bytesRead; i++)
{
if (buffer[i] <= 8 || buffer[i] == 11 || buffer[i] == 12 || buffer[i] == 14 || buffer[i] == 15)
{
isBinary = true;
break;
}
}
}
fclose(file);
return isBinary;
}
/**
* @brief 获取文件首行.
*
* @param filePath
* @return
*/
CString GetFirstLineOfFile(const CString& filePath)
{
CStdioFile file;
if (!file.Open(filePath, CFile::modeRead))
{
return ""; // 打开文件失败,返回空字符串
}
TCHAR firstLine[256];
file.ReadString(firstLine, sizeof(firstLine) / sizeof(TCHAR) - 1);
file.Close();
return CString(firstLine);
}
/**
* @brief 预处理文件.
*
* @param filePath
* @return 临时文件
*/
CString PreprocessFile(CString& filePath)
{
CString path = filePath;
path.MakeLower();
CSplitPath sp(path);
CString ext = sp.GetExtension();
if (!CheckAndCreateDirectory(GetTempDirectory()))
{
return false;
}
if (ext == ".kev")
{
if (!IsBinaryFile(filePath))
{
return filePath;
}
else
{
CString tmpPath = generateTempFile(filePath);
if (XorEncryptFile(filePath, tmpPath))
{
return tmpPath;
}
else
{
return "";
}
}
}
else if (ext == ".dfd")
{
CString ver = GetFirstLineOfFile(filePath);
ver.Trim();
if (ver.CompareNoCase("Version 2022") <= 0)
{
return filePath;
}
else if (ver.CompareNoCase("Version 2022") > 0 && ver.CompareNoCase("Version 2032") <= 0)
{
CString tmpPath = generateTempFile(filePath);
int ret = FromDFDToDFD4(filePath.GetBuffer(), tmpPath.GetBuffer());
if (ret == 0)
{
return "";
}
else
{
return tmpPath;
}
}
else {
return "";
}
}
return filePath;
}
/**
* @brief 后处理文件.
*
* @param filePath
* @return
*/
void PostProcessFile(CString& filePath)
{
CString path = filePath;
path.MakeLower();
CSplitPath sp(path);
CString ext = sp.GetExtension();
if (ext == ".kev")
{
XorEncryptFile(filePath);
}
}
/**
* @brief 清除文件夹内的所有内容.
*
* @param folderPath
*/
void ClearFolder(const CString& folderPath)
{
try
{
// 搜索指定文件夹下的所有文件和文件夹
CString searchPath = folderPath + _T("\\*.*");
CFileFind finder;
BOOL bWorking = finder.FindFile(searchPath);
while (bWorking)
{
bWorking = finder.FindNextFile();
if (finder.IsDots())
continue;
CString filePath = finder.GetFilePath();
if (finder.IsDirectory())
{
// 递归删除子文件夹
ClearFolder(filePath);
RemoveDirectory(filePath);
}
else
{
// 删除文件
DeleteFile(filePath);
}
}
finder.Close();
}
catch (const std::exception&)
{
}
}
/**
* @brief 清空临时文件夹.
*
*/
void ClearTempFolder()
{
ClearFolder(GetTempDirectory());
}
/**
* @brief 检测并创建目录.
*
* @param path
* @return
*/
BOOL CheckAndCreateDirectory(const CString& path)
{
if (!PathFileExists(path))
{
CFileFind finder;
BOOL bFound = finder.FindFile(path);
if (!bFound)
{
// 目录不存在,创建目录
if (CreateDirectory(path, NULL))
{
return TRUE;
}
else
{
// 创建目录失败
return FALSE;
}
}
// 目录已存在
return TRUE;
}
return TRUE;
}
/**
* @brief 产生GUID字符串.
*
* @param guidStr
*/
void generateGUID(char* pGuidStr) {
GUID guid;
CoCreateGuid(&guid);
sprintf(pGuidStr, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
/**
* @brief 存临时文件目录产生临时文件.
*
* @return 临时文件路径
*/
CString generateTempFile(CString& filePath)
{
CSplitPath sp(filePath);
CString ext = sp.GetExtension();
CString tmpPath = GetTempDirectory();
char uuidStr[37];
generateGUID(uuidStr);
tmpPath.Append(uuidStr);
tmpPath.Append(ext);
return tmpPath;
}
/**
* @brief 获取可执行文件所在目录.
*
* @return 当前应用目录
*/
CString GetTempDirectory()
{
CString tempDir = GetExecutableDirectory();
tempDir.Append("\\temp\\");
return tempDir;
}
/**
* @brief 获取可执行文件所在目录.
*
* @return 当前应用目录
*/
CString GetExecutableDirectory()
{
TCHAR buffer[MAX_PATH] = { 0 };
GetModuleFileName(NULL, buffer, MAX_PATH);
PathRemoveFileSpec(buffer);
return CString(buffer);
}