summaryrefslogtreecommitdiff
path: root/src/T2DLL/CPEFile.cpp
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
committerAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
commit37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch)
treeeaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/CPEFile.cpp
downloadt2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz
t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip
initial commit
Diffstat (limited to '')
-rw-r--r--src/T2DLL/CPEFile.cpp248
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);
+}