#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); }