diff --git a/rcedit.gyp b/rcedit.gyp index 49e03be..7e5cfbf 100644 --- a/rcedit.gyp +++ b/rcedit.gyp @@ -10,6 +10,9 @@ 'src/rcedit.rc', 'src/version.h', ], + 'libraries': [ + 'imagehlp.lib', + ], 'msvs_settings': { 'VCLinkerTool': { 'SubSystem': 1, # console executable diff --git a/rcedit.vcxproj b/rcedit.vcxproj index aabf1b3..4f4f31f 100644 --- a/rcedit.vcxproj +++ b/rcedit.vcxproj @@ -45,7 +45,7 @@ MultiThreaded - + imagehlp.lib $(OutDir)$(ProjectName)$(TargetExt) Console diff --git a/src/rescle.cc b/src/rescle.cc index 4cdff4a..fa2d710 100644 --- a/src/rescle.cc +++ b/src/rescle.cc @@ -9,6 +9,7 @@ #include #include +#include #include // wstringstream #include // setw, setfill #include @@ -93,8 +94,8 @@ std::wstring ReadFileToString(const wchar_t* filename) { class ScopedFile { public: - ScopedFile(const WCHAR* path) - : file_(CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) {} + ScopedFile(const WCHAR* path, DWORD access = GENERIC_READ) + : file_(CreateFileW(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) {} ~ScopedFile() { CloseHandle(file_); } operator HANDLE() { return file_; } @@ -568,8 +569,8 @@ bool ResourceUpdater::ChangeRcData(UINT id, const WCHAR* pathToResource) { wchar_t abspath[MAX_PATH] = { 0 }; const auto filePath = _wfullpath(abspath, pathToResource, MAX_PATH) ? abspath : pathToResource; - ScopedFile newRcDataFile(filePath); - if (newRcDataFile == INVALID_HANDLE_VALUE) { + ScopedFile newRcDataFile(filePath); + if (newRcDataFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "Cannot open new data file '%ws'\n", filePath); return false; } @@ -581,13 +582,13 @@ bool ResourceUpdater::ChangeRcData(UINT id, const WCHAR* pathToResource) { } auto& rcData = rcDataLngPairIt->second[id]; - rcData.clear(); + rcData.clear(); rcData.resize(dwFileSize); - - DWORD dwBytesRead{ 0 }; + + DWORD dwBytesRead{ 0 }; if (!ReadFile(newRcDataFile, rcData.data(), dwFileSize, &dwBytesRead, NULL)) { fprintf(stderr, "Cannot read file '%ws'\n", filePath); - return false; + return false; } return true; @@ -701,7 +702,7 @@ bool ResourceUpdater::Commit() { FreeLibrary(module_); module_ = NULL; - ScopedResourceUpdater ru(filename_.c_str(), false); + ScopedResourceUpdater ru(filename_, false); if (ru.Get() == NULL) { return false; } @@ -979,8 +980,8 @@ BOOL CALLBACK ResourceUpdater::OnEnumResourceManifest(HMODULE hModule, LPCTSTR l return TRUE; // Keep going } -ScopedResourceUpdater::ScopedResourceUpdater(const WCHAR* filename, bool deleteOld) - : handle_(BeginUpdateResourceW(filename, deleteOld)) { +ScopedResourceUpdater::ScopedResourceUpdater(std::wstring filename, bool deleteOld) + : filename_(filename), handle_(BeginUpdateResourceW(filename.c_str(), deleteOld)) { } ScopedResourceUpdater::~ScopedResourceUpdater() { @@ -995,7 +996,7 @@ HANDLE ScopedResourceUpdater::Get() const { bool ScopedResourceUpdater::Commit() { commited_ = true; - return EndUpdate(true); + return EndUpdate(true) && UpdateChecksum(); } bool ScopedResourceUpdater::EndUpdate(bool doesCommit) { @@ -1005,4 +1006,45 @@ bool ScopedResourceUpdater::EndUpdate(bool doesCommit) { return bResult ? true : false; } +bool ScopedResourceUpdater::UpdateChecksum() { + const WCHAR* path = filename_.c_str(); + ScopedFile binFile(path, GENERIC_READ|GENERIC_WRITE); + if (binFile == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Cannot open '%ws'\n", path); + return false; + } + DWORD fileSize = GetFileSize(binFile, NULL); + if (fileSize == INVALID_FILE_SIZE) { + fprintf(stderr, "Cannot get file size for '%ws'\n", path); + return false; + } + + HANDLE hFilemap = CreateFileMapping(binFile, NULL, PAGE_READWRITE, 0, 0, NULL); + if (!hFilemap) { + fprintf(stderr, "CreateFileMapping(%ws) failed\n", path); + return false; + } + + void* view = MapViewOfFile(hFilemap, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!view) { + fprintf(stderr, "Cannot map '%ws' into memory\n", path); + CloseHandle(hFilemap); + return false; + } + + bool ret = false; + DWORD originalSum, checkSum; + IMAGE_NT_HEADERS *ntHeader = CheckSumMappedFile(view, fileSize, &originalSum, &checkSum); + if (!ntHeader) { + fprintf(stderr, "CheckSumMappedFile failed\n"); + } else { + ntHeader->OptionalHeader.CheckSum = checkSum; + ret = true; + } + + UnmapViewOfFile(view); + CloseHandle(hFilemap); + return ret; +} + } // namespace rescle diff --git a/src/rescle.h b/src/rescle.h index 713231e..f65ab4d 100644 --- a/src/rescle.h +++ b/src/rescle.h @@ -167,7 +167,7 @@ class ResourceUpdater { class ScopedResourceUpdater { public: - ScopedResourceUpdater(const WCHAR* filename, bool deleteOld); + ScopedResourceUpdater(std::wstring filename, bool deleteOld); ~ScopedResourceUpdater(); HANDLE Get() const; @@ -175,7 +175,9 @@ class ScopedResourceUpdater { private: bool EndUpdate(bool doesCommit); + bool UpdateChecksum(); + std::wstring filename_; HANDLE handle_; bool commited_ = false; };