From 35ae3cca66996ecaf867909577dfa44b19ed81ce Mon Sep 17 00:00:00 2001 From: kichik Date: Wed, 24 Jan 2007 15:55:36 +0000 Subject: [PATCH] applied patch #1643633 - 64bit PE support for CResourceEditor git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4880 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/Platform.h | 32 +++++++++++++++++++++++ Source/ResourceEditor.cpp | 55 +++++++++++++++++++++++++-------------- Source/ResourceEditor.h | 5 ++++ 3 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Source/Platform.h b/Source/Platform.h index 5a2527e7..f34f217b 100644 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -739,6 +739,38 @@ typedef struct _IMAGE_OPTIONAL_HEADER { DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; +typedef struct _IMAGE_OPTIONAL_HEADER64 { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64,*PIMAGE_OPTIONAL_HEADER64; #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b typedef struct _IMAGE_NT_HEADERS { diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp index 2db39184..1145a8aa 100644 --- a/Source/ResourceEditor.cpp +++ b/Source/ResourceEditor.cpp @@ -50,8 +50,9 @@ PIMAGE_NT_HEADERS CResourceEditor::GetNTHeaders(BYTE* pbPE) { if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) throw runtime_error("PE file missing NT signature"); - // Make sure this is a 32-bit PE - if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) + // Make sure this is a supported PE format + if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && + ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) throw runtime_error("Unsupported PE format"); return ntHeaders; @@ -64,10 +65,13 @@ PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory( DWORD *pdwResSecVA /*=NULL*/, DWORD *pdwSectionIndex /*=NULL*/ ) { - if (ConvertEndianness(ntHeaders->OptionalHeader.NumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE) + PIMAGE_DATA_DIRECTORY dataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory); + DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes); + + if (ConvertEndianness(dwNumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE) throw runtime_error("No resource section found"); // Get resource section virtual address - DWORD dwResSecVA = ConvertEndianness(ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + DWORD dwResSecVA = ConvertEndianness(dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); // Pointer to the sections headers array PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); @@ -124,10 +128,11 @@ CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize) { m_ntHeaders = GetNTHeaders(m_pbPE); // No check sum support yet... - if (m_ntHeaders->OptionalHeader.CheckSum) + DWORD* pdwCheckSum = GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, CheckSum); + if (*pdwCheckSum) { // clear checksum (should be [re]calculated after all changes done) - m_ntHeaders->OptionalHeader.CheckSum = 0; + pdwCheckSum = 0; //throw runtime_error("CResourceEditor doesn't yet support check sum"); } @@ -405,28 +410,36 @@ DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) { sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = ConvertEndianness(dwRsrcSizeAligned); // Set the virtual size as well (in memory) sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = ConvertEndianness(dwRsrcSize); - ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize); + (*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory))[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize); // Set the new virtual size of the image - ntHeaders->OptionalHeader.SizeOfImage = AlignVA(ntHeaders->OptionalHeader.SizeOfHeaders); + DWORD* pdwSizeOfImage = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfImage); + *pdwSizeOfImage = AlignVA(*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfHeaders)); for (i = 0; i < wNumberOfSections; i++) { DWORD dwSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize); - ntHeaders->OptionalHeader.SizeOfImage = AlignVA(AdjustVA(ntHeaders->OptionalHeader.SizeOfImage, dwSecSize)); + *pdwSizeOfImage = AlignVA(AdjustVA(*pdwSizeOfImage, dwSecSize)); } // Set the new AddressOfEntryPoint if needed - if (ConvertEndianness(ntHeaders->OptionalHeader.AddressOfEntryPoint) > m_dwResourceSectionVA) - ntHeaders->OptionalHeader.AddressOfEntryPoint = AdjustVA(ntHeaders->OptionalHeader.AddressOfEntryPoint, dwVAAdjustment); + DWORD* pdwAddressOfEntryPoint = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, AddressOfEntryPoint); + if (ConvertEndianness(*pdwAddressOfEntryPoint) > m_dwResourceSectionVA) + *pdwAddressOfEntryPoint = AdjustVA(*pdwAddressOfEntryPoint, dwVAAdjustment); // Set the new BaseOfCode if needed - if (ConvertEndianness(ntHeaders->OptionalHeader.BaseOfCode) > m_dwResourceSectionVA) - ntHeaders->OptionalHeader.BaseOfCode = AdjustVA(ntHeaders->OptionalHeader.BaseOfCode, dwVAAdjustment); + DWORD* pdwBaseOfCode = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, BaseOfCode); + if (ConvertEndianness(*pdwBaseOfCode) > m_dwResourceSectionVA) + *pdwBaseOfCode = AdjustVA(*pdwBaseOfCode, dwVAAdjustment); // Set the new BaseOfData if needed - if (ConvertEndianness(ntHeaders->OptionalHeader.BaseOfData) > m_dwResourceSectionVA) - ntHeaders->OptionalHeader.BaseOfData = AdjustVA(ntHeaders->OptionalHeader.BaseOfData, dwVAAdjustment); + if (ntHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + DWORD* pdwBaseOfData = &((PIMAGE_OPTIONAL_HEADER32)&ntHeaders->OptionalHeader)->BaseOfData; + if (*pdwBaseOfData > m_dwResourceSectionVA) + *pdwBaseOfData = AdjustVA(*pdwBaseOfData, dwVAAdjustment); + } // Refresh the headers of the sections that come after the resource section, and the data directory + DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes); + PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory); for (i = m_dwResourceSectionIndex + 1; i < wNumberOfSections; i++) { if (sectionHeadersArray[i].PointerToRawData) { AdjustVA(sectionHeadersArray[i].PointerToRawData, dwRsrcSizeAligned - dwOldRsrcSize); @@ -434,15 +447,15 @@ DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) { // We must find the right data directory entry before we change the virtual address unsigned int uDataDirIdx = 0; - for (unsigned int j = 0; j < ConvertEndianness(ntHeaders->OptionalHeader.NumberOfRvaAndSizes); j++) - if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) + for (unsigned int j = 0; j < ConvertEndianness(dwNumberOfRvaAndSizes); j++) + if (pDataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) uDataDirIdx = j; sectionHeadersArray[i].VirtualAddress = AdjustVA(sectionHeadersArray[i].VirtualAddress, dwVAAdjustment); // Change the virtual address in the data directory too if (uDataDirIdx) - ntHeaders->OptionalHeader.DataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress; + pDataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress; } // Write the resource section @@ -498,7 +511,8 @@ bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName, if (m_dwResourceSectionIndex == (DWORD) k) { // fix the resources virtual address if it changed - m_ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA; + PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, DataDirectory); + pDataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA; m_dwResourceSectionVA = ConvertEndianness(dwSecVA); } } @@ -712,7 +726,8 @@ DWORD CResourceEditor::AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment) { // Aligns a virtual address to the section alignment DWORD CResourceEditor::AlignVA(DWORD dwVirtualAddress) { - DWORD dwAlignment = ConvertEndianness(m_ntHeaders->OptionalHeader.SectionAlignment); + DWORD dwSectionAlignment = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, SectionAlignment); + DWORD dwAlignment = ConvertEndianness(dwSectionAlignment); dwVirtualAddress = ConvertEndianness(dwVirtualAddress); dwVirtualAddress = RALIGN(dwVirtualAddress, dwAlignment); diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h index 86cad65b..9bd94ec8 100644 --- a/Source/ResourceEditor.h +++ b/Source/ResourceEditor.h @@ -102,6 +102,11 @@ typedef struct RESOURCE_DIRECTORY { MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1]; } *PRESOURCE_DIRECTORY; +#define GetMemberFromOptionalHeader(optionalHeader, member) \ + ( (optionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? \ + &((PIMAGE_OPTIONAL_HEADER32)&optionalHeader)->member : \ + &((PIMAGE_OPTIONAL_HEADER64)&optionalHeader)->member \ + ) class CResourceEditor { public: CResourceEditor(BYTE* pbPE, int iSize);