/********************************************************
* mergebin
* Written by Robert Simpson (robert@blackcastlesoft.com)
*
* Released to the public domain, use at your own risk!
********************************************************/
#include "StdAfx.h"
#include "PEFile.h"
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))
CPEFile::CPEFile(void)
{
m_hMap = NULL;
m_hFile = INVALID_HANDLE_VALUE;
m_pBase = NULL;
}
CPEFile::~CPEFile(void)
{
Close();
}
HRESULT CPEFile::Open(LPCTSTR pszFile, BOOL bReadOnly)
{
HRESULT hr = S_OK;
Close();
m_hFile = CreateFile(pszFile, GENERIC_READ | ((bReadOnly == FALSE) ? GENERIC_WRITE: 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_hFile == INVALID_HANDLE_VALUE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
m_hMap = CreateFileMapping(m_hFile, NULL, (bReadOnly == TRUE) ? PAGE_READONLY:PAGE_READWRITE, 0, 0, NULL);
if (!m_hMap)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
m_pBase = (PIMAGE_DOS_HEADER)MapViewOfFile(m_hMap, FILE_MAP_READ | ((bReadOnly == FALSE) ? FILE_MAP_WRITE:0), 0, 0, 0);
if (!m_pBase)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
}
if (SUCCEEDED(hr))
{
PIMAGE_FILE_HEADER pImageHeader = (PIMAGE_FILE_HEADER)m_pBase;
if (m_pBase->e_magic != IMAGE_DOS_SIGNATURE)
{
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
}
m_pNTHeader = MakePtr(PIMAGE_NT_HEADERS, m_pBase, m_pBase->e_lfanew);
if (IsBadReadPtr(m_pNTHeader, sizeof(m_pNTHeader->Signature)))
{
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
}
else
{
if (m_pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
}
}
}
if (FAILED(hr)) Close();
return hr;
}
void CPEFile::Close(void)
{
if (m_pBase)
{
UnmapViewOfFile(m_pBase);
}
if (m_hMap)
CloseHandle(m_hMap);
if (m_hFile != INVALID_HANDLE_VALUE)
CloseHandle(m_hFile);
m_hMap = NULL;
m_hFile = INVALID_HANDLE_VALUE;
m_pBase = NULL;
}
PIMAGE_SECTION_HEADER CPEFile::GetEnclosingSectionHeader(DWORD rva) const
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(m_pNTHeader);
for (UINT i=0; i < m_pNTHeader->FileHeader.NumberOfSections; i++, section++ )
{
DWORD size = section->Misc.VirtualSize;
if (!size)
size = section->SizeOfRawData;
if ( (rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + size)))
return section;
}
return NULL;
}
LPVOID CPEFile::GetPtrFromRVA(DWORD rva) const
{
PIMAGE_SECTION_HEADER pSectionHdr;
INT delta;
pSectionHdr = GetEnclosingSectionHeader(rva);
if ( !pSectionHdr )
return 0;
delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
return (PVOID) (((LPBYTE)m_pBase) + rva - delta);
}
PIMAGE_SECTION_HEADER CPEFile::GetSectionHeader(LPCSTR name) const
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(m_pNTHeader);
for (UINT i=0; i < m_pNTHeader->FileHeader.NumberOfSections; i++, section++)
{
if (_strnicmp((char *)section->Name,name,IMAGE_SIZEOF_SHORT_NAME) == 0)
return section;
}
return NULL;
}
CPEFile::operator PIMAGE_NT_HEADERS() const
{
if (!m_pBase) return NULL;
return m_pNTHeader;
}
CPEFile::operator PIMAGE_DOS_HEADER() const
{
return m_pBase;
}
CPEFile::operator PIMAGE_COR20_HEADER() const
{
if (!m_pBase) return NULL;
DWORD dwRVA;
dwRVA = m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
if (!dwRVA)
{
return NULL;
}
return ((PIMAGE_COR20_HEADER)GetPtrFromRVA(dwRVA));
}