diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
commit | 37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch) | |
tree | eaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/CPEFile.cpp | |
download | t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip |
initial commit
Diffstat (limited to '')
-rw-r--r-- | src/T2DLL/CPEFile.cpp | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/src/T2DLL/CPEFile.cpp b/src/T2DLL/CPEFile.cpp new file mode 100644 index 0000000..7bb49de --- /dev/null +++ b/src/T2DLL/CPEFile.cpp @@ -0,0 +1,248 @@ +#include "CPEFile.h" + +CPEFile::CPEFile(const CPEFile& other) + : mFile(other.mFile) + , mFileHeader(other.mFileHeader) + , mSectionHeaders(other.mSectionHeaders) + , mRsrcPtr(other.mRsrcPtr) + , mRsrcIndex(other.mRsrcIndex) + , mStartPosition(other.mStartPosition) + , mLength(other.mLength) +{ +} + +CPEFile& CPEFile::operator=(const CPEFile& other) { + mFile = other.mFile; + mFileHeader = other.mFileHeader; + mSectionHeaders = other.mSectionHeaders; + mRsrcPtr = other.mRsrcPtr; + mRsrcIndex = other.mRsrcIndex; + mStartPosition = other.mStartPosition; + mLength = other.mLength; + return *this; +} + +CPEFile::CPEFile() { + mFile = NULL; +} + +CPEFile::~CPEFile() { + Close(); +} + +/*virtual*/ void CPEFile::Close() { + if (mFile) { + mFile->Close(); + delete mFile; + } + mFile = NULL; + + if (mSectionHeaders) + free(mSectionHeaders); + mSectionHeaders = NULL; +} + +/*virtual*/ BOOL CPEFile::Open(const char*filename, unsigned int flags, CFileException*pError) { + BOOL result = false; + +#line 36 + mFile = DEBUG_NEW CFile; + if (mFile->Open(filename, flags, pError)) { + result = Init(); + if (!result) + Close(); + } + + return result; +} + +BOOL CPEFile::Init() { + IMAGE_DOS_HEADER header; + + mSectionHeaders = NULL; + + memset(&header, 0, sizeof(header)); + mFile->Read(&header, sizeof(header)); + if (header.e_magic != IMAGE_DOS_SIGNATURE) + return false; + + mFile->Seek(header.e_lfanew, CFile::begin); + + DWORD magic = 0; + mFile->Read(&magic, sizeof(magic)); + if (magic != IMAGE_NT_SIGNATURE) + return false; + + memset(&mFileHeader, 0, sizeof(mFileHeader)); + mFile->Read(&mFileHeader, sizeof(mFileHeader)); + mFile->Seek(IMAGE_SIZEOF_NT_OPTIONAL_HEADER, CFile::current); + + mSectionHeaders = (IMAGE_SECTION_HEADER *) malloc(sizeof(IMAGE_SECTION_HEADER) * mFileHeader.NumberOfSections); + mFile->Read(mSectionHeaders, sizeof(IMAGE_SECTION_HEADER) * mFileHeader.NumberOfSections); + + int i; + for (i = 0; i < mFileHeader.NumberOfSections; i++) { + if (strcmp((const char *) mSectionHeaders[i].Name, ".rsrc") == 0) + break; + } + + if (i == mFileHeader.NumberOfSections) + return false; + + mRsrcPtr = mSectionHeaders[i].PointerToRawData; + mRsrcIndex = i; + return true; +} + +BOOL CPEFile::EnumResource(CString& s, RESTRACKERWORK& work) { + IMAGE_RESOURCE_DIRECTORY_ENTRY entry; + + if (!EnumResourceDirectory(&entry, work)) + return false; + + GetResourceName(s, entry); + return true; +} + +BOOL CPEFile::EnumResourceDirectory(IMAGE_RESOURCE_DIRECTORY_ENTRY* entry, RESTRACKERWORK& work) { + if (!work.didRead) { + mFile->Seek(mRsrcPtr, CFile::begin); + mFile->Read(&work.directory, sizeof(work.directory)); + work.position = mFile->GetPosition(); + work.didRead = true; + work.nextIndex = 0; + } + + int entryCount = (work.directory.NumberOfNamedEntries + work.directory.NumberOfIdEntries); + if (work.nextIndex >= entryCount) + return false; + + mFile->Seek(work.position + work.nextIndex * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), CFile::begin); + mFile->Read(entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); + memcpy(&work.entry, entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); + work.nextIndex++; + return true; +} + +void CPEFile::GetResourceName(CString& s, IMAGE_RESOURCE_DIRECTORY_ENTRY& entry) { + if (entry.Name & 0x80000000) { + unsigned short len; + mFile->Seek(mRsrcPtr + entry.NameOffset, CFile::begin); + mFile->Read(&len, sizeof(len)); + + char *widebuf = (char *) malloc(len * 2); + mFile->Read(widebuf, len * 2); + + int size = len * 2 + 1; + char *buf = (char *) malloc(size); + memset(buf, 0, size); + + int i; + for (i = 0; i < len; i++) { + buf[i] = widebuf[i * 2]; + } + buf[i] = 0; + + s = buf; + free(widebuf); + free(buf); + } else { + s.Format("#%u", entry.Name); + } + + if (entry.OffsetToData & 0x80000000) + s += "\\"; +} + +void CPEFile::EnterDirectory(RESTRACKERWORK& child, RESTRACKERWORK& parent) { + mFile->Seek(mRsrcPtr + parent.entry.OffsetToDirectory, CFile::begin); + mFile->Read(&child.directory, sizeof(child.directory)); + child.position = mFile->GetPosition(); + child.didRead = true; + child.nextIndex = 0; +} + +/*virtual*/ BOOL CPEFile::Seek(const char* name) { +#line 141 + _ASSERT(strncmp(name, "\\.rsrc", 6) == 0); + + char *nameCopy = (char *) malloc(strlen(name) + 1); + strcpy(nameCopy, name); + + CString str; + str = (char *) NULL; + str = strtok(nameCopy, "\\"); + + RESTRACKERWORK work; + memset(&work, 0, sizeof(work)); + + BOOL flag = false; + + CString str2(""); + + while ((str = strtok(NULL, "\\")) != "") { + if (flag) { + RESTRACKERWORK child; + EnterDirectory(child, work); + work = child; + } + flag = false; + + while (EnumResource(str2, work) == 1) { + if (_stricmp(str2, str) == 0 || _stricmp(str2, str + "\\") == 0) { + flag = true; + break; + } + } + + if (!flag) + return false; + } + + free(nameCopy); + + if (str2.Right(1) == "\\") + return false; + + IMAGE_RESOURCE_DATA_ENTRY dataEntry; + + mFile->Seek(mRsrcPtr + work.entry.OffsetToData, CFile::begin); + mFile->Read(&dataEntry, sizeof(dataEntry)); + + mStartPosition = dataEntry.OffsetToData - (mSectionHeaders[mRsrcIndex].VirtualAddress - mSectionHeaders[mRsrcIndex].PointerToRawData); + mLength = dataEntry.Size; + + mFile->Seek(mStartPosition, CFile::begin); + + return true; +} + +/*virtual*/ unsigned long CPEFile::GetLength() { + return mLength; +} + +/*virtual*/ unsigned long CPEFile::GetPosition() { + return mFile->GetPosition() - mStartPosition; +} + +/*virtual*/ long CPEFile::Seek(long offset, unsigned int from) { + if (from == CFile::begin) + return mFile->Seek(offset + mStartPosition, from) - mStartPosition; + else + return mFile->Seek(offset, from) - mStartPosition; +} + +/*virtual*/ unsigned int CPEFile::Read(void* buf, unsigned int len) { + int remaining = mLength - GetPosition(); + if (remaining < 0 || len > remaining) + len = remaining; + return mFile->Read(buf, len); +} + +/*virtual*/ void CPEFile::Write(void* buf, unsigned int len) { + int remaining = mLength - GetPosition(); + if (remaining < 0 || len > remaining) + MessageBox(NULL, "CPEFile::Write overrun", "ERROR", MB_OK); + else + mFile->Write(buf, len); +} |