rockbox/utils/zenutils/libraries/pelib-0.9/pelib/MzHeader.cpp

585 lines
14 KiB
C++
Raw Normal View History

/*
* MzHeader.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "MzHeader.h"
#include <iostream>
namespace PeLib
{
/**
* Reads data from an InputBuffer into the struct that represents the MZ header.
* It's required that the size of the input buffer is at least as big as the
* size of a MZ header. Otherwise we get undefined behaviour.
* @param ibBuffer InputBuffer that holds the data.
* @return A non-zero value is returned if a problem occured.
**/
void MzHeader::read(InputBuffer& ibBuffer)
{
ibBuffer >> m_idhHeader.e_magic;
ibBuffer >> m_idhHeader.e_cblp;
ibBuffer >> m_idhHeader.e_cp;
ibBuffer >> m_idhHeader.e_crlc;
ibBuffer >> m_idhHeader.e_cparhdr;
ibBuffer >> m_idhHeader.e_minalloc;
ibBuffer >> m_idhHeader.e_maxalloc;
ibBuffer >> m_idhHeader.e_ss;
ibBuffer >> m_idhHeader.e_sp;
ibBuffer >> m_idhHeader.e_csum;
ibBuffer >> m_idhHeader.e_ip;
ibBuffer >> m_idhHeader.e_cs;
ibBuffer >> m_idhHeader.e_lfarlc;
ibBuffer >> m_idhHeader.e_ovno;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res)/sizeof(m_idhHeader.e_res[0]);i++)
{
ibBuffer >> m_idhHeader.e_res[i];
}
ibBuffer >> m_idhHeader.e_oemid;
ibBuffer >> m_idhHeader.e_oeminfo;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res2)/sizeof(m_idhHeader.e_res2[0]);i++)
{
ibBuffer >> m_idhHeader.e_res2[i];
}
ibBuffer >> m_idhHeader.e_lfanew;
}
/**
* Tests if the currently loaded MZ header is a valid MZ header.
* Note that this function does not check if the address to the PE header is valid as this is not possible.
* Actually, the only thing this function checks is if the e_magic value is set to 0x5A4D (IMAGE_DOS_SIGNATURE).
* Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now.
* @return A boolean value that indicates if the MZ header is correct or not.
**/
bool MzHeader::isValid() const
{
// The only thing that matters on Windows 2K is the e_magic value. The entire rest is for DOS compatibility.
return isValid(e_magic);
}
bool MzHeader::isValid(Field f) const
{
if (f == e_magic)
{
return m_idhHeader.e_magic == PELIB_IMAGE_DOS_SIGNATURE;
}
else
{
return true;
}
}
/**
* Corrects all erroneous values of the current MZ header. Note that this function does not correct the
* pointer to the PE header.
* Actually, the only thing this function corrects is the e_magic value.
* Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now.
**/
void MzHeader::makeValid()
{
// The only thing that matters on Windows is the e_magic value. The entire rest is for DOS compatibility.
setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE);
}
void MzHeader::makeValid(Field f)
{
if (f == e_magic)
{
setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE);
}
}
/**
* Reads the MZ header from a file. Note that this function does not verify if a file is actually a MZ file.
* For this purpose see #PeFile::MzHeader::isValid. The reason for this is simple: Otherwise it might not
* be possible to load damaged PE files to repair them.
* @param strFilename Name of the file which will be read.
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::read(const std::string& strFilename)
{
std::ifstream ifFile(strFilename.c_str(), std::ios::binary);
if (!ifFile)
{
return ERROR_OPENING_FILE;
}
if (fileSize(ifFile) < PELIB_IMAGE_DOS_HEADER::size())
{
return ERROR_INVALID_FILE;
}
ifFile.seekg(0, std::ios::beg);
originalOffset = 0;
std::vector<byte> vBuffer(PELIB_IMAGE_DOS_HEADER::size());
ifFile.read(reinterpret_cast<char*>(&vBuffer[0]), static_cast<unsigned int>(vBuffer.size()));
ifFile.close();
InputBuffer ibBuffer(vBuffer);
read(ibBuffer);
return NO_ERROR;
}
/**
* Reads the MZ header from memory. A pointer to a location in memory is passed and the data
* at this location is treated like a MZ header structure. The MZ header does not need to be valid.
* @param pcBuffer Pointer to a MZ header.
* @param uiSize Length of the buffer.
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::read(unsigned char* pcBuffer, unsigned int uiSize, unsigned int originalOffs)
{
if (uiSize < PELIB_IMAGE_DOS_HEADER::size())
{
return ERROR_INVALID_FILE;
}
std::vector<byte> vBuffer(pcBuffer, pcBuffer + uiSize);
for (int i=0;i<0x40;i++) std::cout << std::hex << (int)vBuffer[i] << " ";
originalOffset = originalOffs;
InputBuffer ibBuffer(vBuffer);
read(ibBuffer);
return NO_ERROR;
}
/**
* Rebuilds the MZ header so that it can be written to a file. It's not guaranteed that the
* MZ header will be valid. If you want to make sure that the MZ header will be valid you
* must call #PeLib::MzHeader::makeValid first.
* @param vBuffer Buffer where the rebuilt MZ header will be stored.
**/
void MzHeader::rebuild(std::vector<byte>& vBuffer) const
{
OutputBuffer obBuffer(vBuffer);
obBuffer << m_idhHeader.e_magic;
obBuffer << m_idhHeader.e_cblp;
obBuffer << m_idhHeader.e_cp;
obBuffer << m_idhHeader.e_crlc;
obBuffer << m_idhHeader.e_cparhdr;
obBuffer << m_idhHeader.e_minalloc;
obBuffer << m_idhHeader.e_maxalloc;
obBuffer << m_idhHeader.e_ss;
obBuffer << m_idhHeader.e_sp;
obBuffer << m_idhHeader.e_csum;
obBuffer << m_idhHeader.e_ip;
obBuffer << m_idhHeader.e_cs;
obBuffer << m_idhHeader.e_lfarlc;
obBuffer << m_idhHeader.e_ovno;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res)/sizeof(m_idhHeader.e_res[0]);i++)
{
obBuffer << m_idhHeader.e_res[i];
}
obBuffer << m_idhHeader.e_oemid;
obBuffer << m_idhHeader.e_oeminfo;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res2)/sizeof(m_idhHeader.e_res2[0]);i++)
{
obBuffer << m_idhHeader.e_res2[i];
}
obBuffer << m_idhHeader.e_lfanew;
}
/**
* Returns the size of the MZ header. This size is actually always sizeof(IMAGE_DOS_HEADER) (== 0x40)
* because the MZ header is a header of constant size if you disregard the dos stub. If you want to know the
* size of the MZ header + the size of the dos stub check #PeLib::MzHeader::getAddressOfPeHeader.
* @return Size of the MZ header.
**/
unsigned int MzHeader::size() const
{
return sizeof(m_idhHeader);
}
/**
* Writes the current MZ header to a file. The file does not have to exist. If it doesn't exist
* it will be created.
* @param strFilename Name of the file the header will be written to.
* @param dwOffset Offset the header will be written to (defaults to 0).
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::write(const std::string& strFilename, dword dwOffset = 0) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(dwOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(&vBuffer[0]), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return NO_ERROR;
}
/**
* Returns the MZ header's e_magic value.
**/
word MzHeader::getMagicNumber() const
{
return m_idhHeader.e_magic;
}
/**
* Returns the MZ header's e_cblp value.
**/
word MzHeader::getBytesOnLastPage() const
{
return m_idhHeader.e_cblp;
}
/**
* Returns the MZ header's e_cp value.
**/
word MzHeader::getPagesInFile() const
{
return m_idhHeader.e_cp;
}
/**
* Returns the MZ header's e_crlc value.
**/
word MzHeader::getRelocations() const
{
return m_idhHeader.e_crlc;
}
/**
* Returns the MZ header's e_cparhdr value.
**/
word MzHeader::getSizeOfHeader() const
{
return m_idhHeader.e_cparhdr;
}
/**
* Returns the MZ header's e_minalloc value.
**/
word MzHeader::getMinExtraParagraphs() const
{
return m_idhHeader.e_minalloc;
}
/**
* Returns the MZ header's e_maxalloc value.
**/
word MzHeader::getMaxExtraParagraphs() const
{
return m_idhHeader.e_maxalloc;
}
/**
* Returns the MZ header's e_ss value.
**/
word MzHeader::getSsValue() const
{
return m_idhHeader.e_ss;
}
/**
* Returns the MZ header's e_sp value.
**/
word MzHeader::getSpValue() const
{
return m_idhHeader.e_sp;
}
/**
* Returns the MZ header's e_csum value.
**/
word MzHeader::getChecksum() const
{
return m_idhHeader.e_csum;
}
/**
* Returns the MZ header's e_ip value.
**/
word MzHeader::getIpValue() const
{
return m_idhHeader.e_ip;
}
/**
* Returns the MZ header's e_cs value.
**/
word MzHeader::getCsValue() const
{
return m_idhHeader.e_cs;
}
/**
* Returns the MZ header's e_lfarlc value.
**/
word MzHeader::getAddrOfRelocationTable() const
{
return m_idhHeader.e_lfarlc;
}
/**
* Returns the MZ header's e_ovno value.
**/
word MzHeader::getOverlayNumber() const
{
return m_idhHeader.e_ovno;
}
/**
* Returns the MZ header's e_oemid value.
**/
word MzHeader::getOemIdentifier() const
{
return m_idhHeader.e_oemid;
}
/**
* Returns the MZ header's e_oeminfo value.
**/
word MzHeader::getOemInformation() const
{
return m_idhHeader.e_oeminfo;
}
/**
* Returns the MZ header's e_lfanew value.
**/
dword MzHeader::getAddressOfPeHeader() const
{
return m_idhHeader.e_lfanew;
}
/**
* Returns the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-3)
**/
word MzHeader::getReservedWords1(unsigned int uiNr) const
{
return m_idhHeader.e_res[uiNr];
}
/**
* Returns the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-9)
**/
word MzHeader::getReservedWords2(unsigned int uiNr) const
{
return m_idhHeader.e_res2[uiNr];
}
/**
* Sets the MZ header's e_magic value.
* @param wValue The new value of e_magic.
**/
void MzHeader::setMagicNumber(word wValue)
{
m_idhHeader.e_magic = wValue;
}
/**
* Sets the MZ header's e_cblp value.
* @param wValue The new value of e_cblp.
**/
void MzHeader::setBytesOnLastPage(word wValue)
{
m_idhHeader.e_cblp = wValue;
}
/**
* Sets the MZ header's e_cp value.
* @param wValue The new value of e_cp.
**/
void MzHeader::setPagesInFile(word wValue)
{
m_idhHeader.e_cp = wValue;
}
/**
* Sets the MZ header's e_crlc value.
* @param wValue The new value of e_crlc.
**/
void MzHeader::setRelocations(word wValue)
{
m_idhHeader.e_crlc = wValue;
}
/**
* Sets the MZ header's e_cparhdr value.
* @param wValue The new value of e_cparhdr.
**/
void MzHeader::setSizeOfHeader(word wValue)
{
m_idhHeader.e_cparhdr = wValue;
}
/**
* Sets the MZ header's e_minalloc value.
* @param wValue The new value of e_minalloc.
**/
void MzHeader::setMinExtraParagraphs(word wValue)
{
m_idhHeader.e_minalloc = wValue;
}
/**
* Sets the MZ header's e_maxalloc value.
* @param wValue The new value of e_maxalloc.
**/
void MzHeader::setMaxExtraParagraphs(word wValue)
{
m_idhHeader.e_maxalloc = wValue;
}
/**
* Sets the MZ header's e_ss value.
* @param wValue The new value of e_ss.
**/
void MzHeader::setSsValue(word wValue)
{
m_idhHeader.e_ss = wValue;
}
/**
* Sets the MZ header's e_sp value.
* @param wValue The new value of e_sp.
**/
void MzHeader::setSpValue(word wValue)
{
m_idhHeader.e_sp = wValue;
}
/**
* Sets the MZ header's e_csum value.
* @param wValue The new value of e_csum.
**/
void MzHeader::setChecksum(word wValue)
{
m_idhHeader.e_csum = wValue;
}
/**
* Sets the MZ header's e_ip value.
* @param wValue The new value of e_ip.
**/
void MzHeader::setIpValue(word wValue)
{
m_idhHeader.e_ip = wValue;
}
/**
* Sets the MZ header's e_cs value.
* @param wValue The new value of e_cs.
**/
void MzHeader::setCsValue(word wValue)
{
m_idhHeader.e_cs = wValue;
}
/**
* Sets the MZ header's e_lfarlc value.
* @param wValue The new value of e_lfarlc.
**/
void MzHeader::setAddrOfRelocationTable(word wValue)
{
m_idhHeader.e_lfarlc = wValue;
}
/**
* Sets the MZ header's e_ovno value.
* @param wValue The new value of e_ovno.
**/
void MzHeader::setOverlayNumber(word wValue)
{
m_idhHeader.e_ovno = wValue;
}
/**
* Sets the MZ header's e_oemid value.
* @param wValue The new value of e_oemid.
**/
void MzHeader::setOemIdentifier(word wValue)
{
m_idhHeader.e_oemid = wValue;
}
/**
* Sets the MZ header's e_oeminfo value.
* @param wValue The new value of e_oeminfo.
**/
void MzHeader::setOemInformation(word wValue)
{
m_idhHeader.e_oeminfo = wValue;
}
/**
* Sets the MZ header's e_lfanew value.
* @param lValue The new value of e_lfanew.
**/
void MzHeader::setAddressOfPeHeader(dword lValue)
{
m_idhHeader.e_lfanew = lValue;
}
/**
* Sets the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-3)
* @param wValue The new value of e_res[nr].
**/
void MzHeader::setReservedWords1(unsigned int uiNr, word wValue)
{
m_idhHeader.e_res[uiNr] = wValue;
}
/**
* Sets the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res2 array (valid range: 0-9)
* @param wValue The new value of e_res[nr].
**/
void MzHeader::setReservedWords2(unsigned int uiNr, word wValue)
{
m_idhHeader.e_res2[uiNr] = wValue;
}
}