From 14c7f45cdae826f88dc539c8c38dd95caf305731 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 11 Jul 2008 15:50:46 +0000 Subject: Add zook's ZenUtils to SVN git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657 --- .../libraries/pelib-0.9/pelib/ImportDirectory.h | 1139 ++++++++++++++++++++ 1 file changed, 1139 insertions(+) create mode 100755 utils/zenutils/libraries/pelib-0.9/pelib/ImportDirectory.h (limited to 'utils/zenutils/libraries/pelib-0.9/pelib/ImportDirectory.h') diff --git a/utils/zenutils/libraries/pelib-0.9/pelib/ImportDirectory.h b/utils/zenutils/libraries/pelib-0.9/pelib/ImportDirectory.h new file mode 100755 index 0000000000..6578f0712a --- /dev/null +++ b/utils/zenutils/libraries/pelib-0.9/pelib/ImportDirectory.h @@ -0,0 +1,1139 @@ +/* +* ImportDirectory.h - 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. +*/ + +#ifndef IMPORTDIRECTORY_H +#define IMPORTDIRECTORY_H + +#include "PeLibAux.h" +#include "PeHeader.h" + +namespace PeLib +{ + /// Parameter for functions that can operate on the OLDDIR or new import directory. + enum currdir {OLDDIR = 1, NEWDIR}; + + class PeLibException; + + /// Class that handles import directories. + /** + * This class can read import directories from existing PE files or start completely from scratch. + * Modifying import directories and writing them to files is also possible. + * It's worthy to note that many functions require an extra parameter of type currdir + * because the structure of import directories make it necessary that the OLDDIR import directory + * must be preserved. That's why some functions (like adding and removing) imported functions + * only exist for the new import directory, not for the one which is already written to the file. + * \todo Adding functions by ordinal doesn't work yet (rebuild needs to be changed). + * \todo Somehow store the rvas of the chunks in the file. + **/ + template + class ImportDirectory + { + typedef typename std::vector >::iterator ImpDirFileIterator; + typedef typename std::vector >::const_iterator ConstImpDirFileIterator; + + private: + /// Stores information about already imported DLLs. + std::vector > m_vOldiid; + /// Stores information about imported DLLs which will be added. + std::vector > m_vNewiid; + + // I can't convince Borland C++ to compile the function outside of the class declaration. + // That's why the function definition is here. + /// Tests if a certain function is imported. + template bool hasFunction(std::string strFilename, T value, bool(PELIB_THUNK_DATA::* comp)(T) const) const + { + ConstImpDirFileIterator FileIter = m_vOldiid.begin(); + ConstImpDirFileIterator EndIter = m_vOldiid.end(); + + for (int i=0;i<=1;i++) // Loop once for m_vOldiid and once for m_vNewiid + { + do + { + FileIter = std::find_if(FileIter, EndIter, std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); + + if (FileIter != EndIter) + { + typename std::vector >::const_iterator Iter = std::find_if(FileIter->originalfirstthunk.begin(), FileIter->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(comp), value)); + if (Iter != FileIter->originalfirstthunk.end()) + { + return true; + } + ++FileIter; + } + } + while (FileIter != EndIter); + + FileIter = m_vNewiid.begin(); + EndIter = m_vNewiid.end(); + } + + return false; + } + + + public: + + /// Add a function to the import directory. + int addFunction(const std::string& strFilename, word wHint); // EXPORT _byHint + /// Add a function to the import directory. + int addFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName + + /// Get the ID of a file through it's name. + unsigned int getFileIndex(const std::string& strFilename, currdir cdDir) const; // EXPORT + /// Get the ID of a function through it's name. + unsigned int getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const; // EXPORT + + /// Get the name of an imported file. + std::string getFileName(dword dwFilenr, currdir cdDir) const; // EXPORT + + void setFileName(dword filenr, currdir dir, const std::string& name); // EXPORT + + /// Get the hint of an imported function. + word getFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT + void setFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir, word value); // EXPORT + /// Get the name of an imported function. + std::string getFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT + void setFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir, const std::string& functionName); // EXPORT + /// Get the number of files which are imported. + dword getNumberOfFiles(currdir cdDir) const; // EXPORT + /// Get the number of fucntions which are imported by a specific file. + dword getNumberOfFunctions(dword dwFilenr, currdir cdDir) const; // EXPORT + /// Read a file's import directory. + int read(const std::string& strFilename, unsigned int uiOffset, unsigned int uiSize, const PeHeaderT& pehHeader); // EXPORT + /// Rebuild the import directory. + void rebuild(std::vector& vBuffer, dword dwRva, bool fixEntries = true) const; // EXPORT + /// Remove a file from the import directory. + int removeFile(const std::string& strFilename); // EXPORT + /// Remove a function from the import directory. + int removeFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName + /// Remove a function from the import directory. + int removeFunction(const std::string& strFilename, word wHint); // EXPORT _byHint + /// Returns the size of the current import directory. + unsigned int size() const; // EXPORT + /// Writes the import directory to a file. + int write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva); // EXPORT + + /// Returns the FirstThunk value of a function. + dword getFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT _byNumber + void setFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value); // EXPORT _byNumber + /// Returns the OriginalFirstThunk value of a function. + dword getOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT _byNumber + void setOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value); // EXPORT + +// dword getFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); +// dword getOriginalFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); + + /// Returns the FirstThunk value of a file. + dword getFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + /// Returns the OriginalFirstThunk value of a file. + dword getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + /// Returns the ForwarderChain value of a file. + dword getForwarderChain(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + dword getRvaOfName(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + /// Returns the TimeDateStamp value of a file. + dword getTimeDateStamp(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + + /// Returns the FirstThunk value of a file. + dword getFirstThunk(dword dwFilenr, currdir cdDir) const; // EXPORT + void setFirstThunk(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function + /// Returns the OriginalFirstThunk value of a file. + dword getOriginalFirstThunk(dword dwFilenr, currdir cdDir) const; // EXPORT + void setOriginalFirstThunk(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function + /// Returns the ForwarderChain value of a file. + dword getForwarderChain(dword dwFilenr, currdir cdDir) const; // EXPORT _byNumber + void setForwarderChain(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function + dword getRvaOfName(dword dwFilenr, currdir cdDir) const; // EXPORT _byNumber + void setRvaOfName(dword dwFilenr, currdir cdDir, dword value); // EXPORT + /// Returns the TimeDateStamp value of a file. + dword getTimeDateStamp(dword dwFilenr, currdir cdDir) const; // EXPORT + void setTimeDateStamp(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber + +// word getFunctionHint(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); + }; + + /** + * Add another import (by Ordinal) to the current file. Note that the import table is not automatically updated. + * The new imported functions will be added when you recalculate the import table as it's necessary + * to specify the address the import table will have in the file. + * @param strFilename The name of a DLL. + * @param wHint The ordinal of the function in the DLL. + **/ + template + int ImportDirectory::addFunction(const std::string& strFilename, word wHint) + { + if (hasFunction(strFilename, wHint, &PELIB_THUNK_DATA::equalHint)) + { + return ERROR_DUPLICATE_ENTRY; + } + + // Find the imported file. + ImpDirFileIterator FileIter = std::find_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); + + PELIB_IMAGE_IMPORT_DIRECTORY iid; + PELIB_THUNK_DATA td; + td.hint = wHint; + td.itd.Ordinal = wHint | PELIB_IMAGE_ORDINAL_FLAGS::IMAGE_ORDINAL_FLAG; + iid.name = strFilename; + if (FileIter == m_vNewiid.end()) + { + iid.originalfirstthunk.push_back(td); + iid.firstthunk.push_back(td); + m_vNewiid.push_back(iid); + } + else + { + FileIter->originalfirstthunk.push_back(td); + FileIter->firstthunk.push_back(td); + } + + return NO_ERROR; + } + + /** + * Add a function to the Import Directory. + * @param strFilename Name of the file which will be imported + * @param strFuncname Name of the function which will be imported. + **/ + template + int ImportDirectory::addFunction(const std::string& strFilename, const std::string& strFuncname) + { + if (hasFunction(strFilename, strFuncname, &PELIB_THUNK_DATA::equalFunctionName)) + { + return ERROR_DUPLICATE_ENTRY; + } + + // Find the imported file. + ImpDirFileIterator FileIter = std::find_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); + + PELIB_IMAGE_IMPORT_DIRECTORY iid; + PELIB_THUNK_DATA td; + td.fname = strFuncname; + iid.name = strFilename; + if (FileIter == m_vNewiid.end()) + { + iid.originalfirstthunk.push_back(td); + iid.firstthunk.push_back(td); + m_vNewiid.push_back(iid); + } + else + { + FileIter->originalfirstthunk.push_back(td); + FileIter->firstthunk.push_back(td); + } + + return NO_ERROR; + } + + /** + * Searches through the import directory and returns the number of the import + * directory entry which belongs to the given filename. + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return The ID of an imported file. + **/ + template + unsigned int ImportDirectory::getFileIndex(const std::string& strFilename, currdir cdDir) const + { + const std::vector >* currDir; + + if (cdDir == OLDDIR) + { + currDir = &m_vOldiid; + } + else + { + currDir = &m_vNewiid; + } + + ConstImpDirFileIterator FileIter = std::find_if(currDir->begin(), currDir->end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); + + if (FileIter != currDir->end()) + { + return static_cast(std::distance(currDir->begin(), FileIter)); + } + else + { + return -1; + // throw Exceptions::InvalidName(ImportDirectoryId, __LINE__); + } + + return NO_ERROR; + } + + /** + * Searches through an imported file for a specific function. + * @param strFilename Name of the imported file. + * @param strFuncname Name of the imported function. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return ID of the imported function. + **/ + template + unsigned int ImportDirectory::getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const + { + unsigned int uiFile = getFileIndex(strFilename, cdDir); + + for (unsigned int i=0;i + std::string ImportDirectory::getFileName(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].name; + else return m_vNewiid[dwFilenr].name; + } + + template + void ImportDirectory::setFileName(dword filenr, currdir dir, const std::string& name) + { + if (dir == OLDDIR) m_vOldiid[filenr].name = name; + else m_vNewiid[filenr].name = name; + } + + /** + * Get the name of an imported function. + * @param dwFilenr Identifies which file should be checked. + * @param dwFuncnr Identifies which function should be checked. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return Name of an imported function. + * \todo Marked line is unsafe (function should be rewritten). + **/ + template + std::string ImportDirectory::getFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + // Unsafe + if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) + { + return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname; + } + else + { + return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname; + } + } + else + { + if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk) + { + return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname; + } + else + { + return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname; + } + } + } + + template + void ImportDirectory::setFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir, const std::string& functionName) + { + if (cdDir == OLDDIR) + { + // Unsafe + if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) + { + m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName; + } + else + { + m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName; + } + } + else + { + if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk) + { + m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName; + } + else + { + m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName; + } + } + } + + /** + * Get the hint of an imported function. + * @param dwFilenr Identifies which file should be checked. + * @param dwFuncnr Identifies which function should be checked. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return Hint of an imported function. + **/ + template + word ImportDirectory::getFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) + { + return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint; + } + else + { + return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint; + } + } + else return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint; + } + + template + void ImportDirectory::setFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir, word value) + { + if (cdDir == OLDDIR) + { + if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) + { + m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value; + } + else + { + m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint = value; + } + } + else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value; + } + + /** + * Get the number of files which are currently being imported. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return Number of files which are currently being imported. + **/ + template + dword ImportDirectory::getNumberOfFiles(currdir cdDir) const + { + if (cdDir == OLDDIR) return static_cast(m_vOldiid.size()); + else return static_cast(m_vNewiid.size()); + } + + /** + * Get the number of functions which are currently being imported from a specific file. + * @param dwFilenr Identifies which file should be checked. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return Number of functions which are currently being imported from a specific file. + **/ + template + dword ImportDirectory::getNumberOfFunctions(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) return static_cast(m_vOldiid[dwFilenr].firstthunk.size()); + else return static_cast(m_vNewiid[dwFilenr].firstthunk.size()); + } + + /** + * Read an import directory from a file. + * \todo Check if streams failed. + * @param strFilename Name of the file which will be read. + * @param uiOffset Offset of the import directory (see #PeLib::PeHeader::getIDImportRVA). + * @param uiSize Size of the import directory (see #PeLib::PeHeader::getIDImportSize). + * @param pehHeader A valid PE header. + **/ + template + int ImportDirectory::read(const std::string& strFilename, unsigned int uiOffset, unsigned int uiSize, const PeHeaderT& pehHeader) + { + std::ifstream ifFile(strFilename.c_str(), std::ios_base::binary); + + if (!ifFile) + { + return ERROR_OPENING_FILE; + } + + unsigned int uiFileSize = fileSize(ifFile); + + if (uiFileSize < uiOffset + uiSize) + { + return ERROR_INVALID_FILE; + } + + ifFile.seekg(uiOffset, std::ios_base::beg); + + std::vector vImportdirectory(uiSize); + ifFile.read(reinterpret_cast(&vImportdirectory[0]), uiSize); + + PELIB_IMAGE_IMPORT_DIRECTORY iidCurr; + unsigned int uiDesccounter = 0; + + InputBuffer inpBuffer(vImportdirectory); + + std::vector > vOldIidCurr; + + do // Read and store all descriptors + { + inpBuffer >> iidCurr.impdesc.OriginalFirstThunk; + inpBuffer >> iidCurr.impdesc.TimeDateStamp; + inpBuffer >> iidCurr.impdesc.ForwarderChain; + inpBuffer >> iidCurr.impdesc.Name; + inpBuffer >> iidCurr.impdesc.FirstThunk; + + if (iidCurr.impdesc.OriginalFirstThunk != 0 || iidCurr.impdesc.TimeDateStamp != 0 || iidCurr.impdesc.ForwarderChain != 0 || + iidCurr.impdesc.Name != 0 || iidCurr.impdesc.FirstThunk != 0) + { + vOldIidCurr.push_back(iidCurr); + } + + uiDesccounter++; + + if (uiSize < (uiDesccounter + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size()) break; + } while (iidCurr.impdesc.OriginalFirstThunk != 0 || iidCurr.impdesc.TimeDateStamp != 0 || iidCurr.impdesc.ForwarderChain != 0 || + iidCurr.impdesc.Name != 0 || iidCurr.impdesc.FirstThunk != 0); + + char namebuffer[2] = {0}; + + // Name + for (unsigned int i=0;i(pehHeader.rvaToOffset(vOldIidCurr[i].impdesc.Name)), std::ios_base::beg); + + std::string dllname = ""; + + do + { + ifFile.read(namebuffer, 1); + if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte + dllname += namebuffer; + } while (true); + + vOldIidCurr[i].name = dllname; + + } + + // OriginalFirstThunk + for (unsigned int i=0;i tdCurr; + dword uiVaoft = vOldIidCurr[i].impdesc.OriginalFirstThunk; + + if (!uiVaoft) + { + continue; + } + + ifFile.seekg(static_cast(pehHeader.rvaToOffset(uiVaoft)), std::ios_base::beg); + + do + { + if (uiFileSize < pehHeader.rvaToOffset(uiVaoft) + sizeof(tdCurr.itd.Ordinal)) + { + return ERROR_INVALID_FILE; + } + uiVaoft += sizeof(tdCurr.itd.Ordinal); + + ifFile.read(reinterpret_cast(&tdCurr.itd.Ordinal), sizeof(tdCurr.itd.Ordinal)); + if (tdCurr.itd.Ordinal) vOldIidCurr[i].originalfirstthunk.push_back(tdCurr); + } while (tdCurr.itd.Ordinal); + } + + // FirstThunk + for (unsigned int i=0;i tdCurr; + + ifFile.seekg(static_cast(pehHeader.rvaToOffset(uiVaoft)), std::ios_base::beg); + + do + { + if (uiFileSize < pehHeader.rvaToOffset(uiVaoft) + sizeof(tdCurr.itd.Ordinal)) + { + return ERROR_INVALID_FILE; + } + + uiVaoft += sizeof(tdCurr.itd.Ordinal); + + ifFile.read(reinterpret_cast(&tdCurr.itd.Ordinal), sizeof(tdCurr.itd.Ordinal)); + if (tdCurr.itd.Ordinal) vOldIidCurr[i].firstthunk.push_back(tdCurr); + } while (tdCurr.itd.Ordinal); + } + + // Names + for (unsigned int i=0;i::IMAGE_ORDINAL_FLAG) + { + vOldIidCurr[i].originalfirstthunk[j].hint = 0; + continue; + } + + ifFile.seekg(static_cast(pehHeader.rvaToOffset(vOldIidCurr[i].originalfirstthunk[j].itd.Ordinal)), std::ios_base::beg); + + ifFile.read(reinterpret_cast(&vOldIidCurr[i].originalfirstthunk[j].hint), sizeof(vOldIidCurr[i].originalfirstthunk[j].hint)); + + if (!ifFile) + return ERROR_INVALID_FILE; + + std::string funcname = ""; + do + { + ifFile.read(namebuffer, 1); + if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte + funcname += namebuffer; + } while (true); + + vOldIidCurr[i].originalfirstthunk[j].fname = funcname; + } + } + else + { + for (unsigned int j=0;j::IMAGE_ORDINAL_FLAG) + { + continue; + } + + ifFile.seekg(static_cast(pehHeader.rvaToOffset(vOldIidCurr[i].firstthunk[j].itd.Ordinal)), std::ios_base::beg); + + ifFile.read(reinterpret_cast(&vOldIidCurr[i].firstthunk[j].hint), sizeof(vOldIidCurr[i].firstthunk[j].hint)); + + if (!ifFile) + return ERROR_INVALID_FILE; + + std::string funcname = ""; + do + { + ifFile.read(namebuffer, 1); + if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte + funcname += namebuffer; + } while (true); + + vOldIidCurr[i].firstthunk[j].fname = funcname; + } + } + } + std::swap(vOldIidCurr, m_vOldiid); + return NO_ERROR; + } + + /** + * Rebuilds the import directory. + * @param vBuffer Buffer the rebuilt import directory will be written to. + * @param dwRva The RVA of the ImportDirectory in the file. + * \todo uiSizeoffuncnames is not used. + **/ + template + void ImportDirectory::rebuild(std::vector& vBuffer, dword dwRva, bool fixEntries) const + { + unsigned int uiImprva = dwRva; + unsigned int uiSizeofdescriptors = (static_cast(m_vNewiid.size() + m_vOldiid.size()) + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size(); + + unsigned int uiSizeofdllnames = 0, uiSizeoffuncnames = 0; + unsigned int uiSizeofoft = 0; + + for (unsigned int i=0;i(m_vNewiid[i].name.size()) + 1; + uiSizeofoft += (static_cast(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); + + for(unsigned int j=0;j(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3); + } + } + +// for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); +// } + + OutputBuffer obBuffer(vBuffer); + + // Rebuild IMAGE_IMPORT_DESCRIPTORS + for (unsigned int i=0;i(m_vNewiid[j-1].originalfirstthunk.size()) + 1) * PELIB_IMAGE_THUNK_DATA::size(); + } + + obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.OriginalFirstThunk); + obBuffer << m_vNewiid[i].impdesc.TimeDateStamp; + obBuffer << m_vNewiid[i].impdesc.ForwarderChain; + dword dwPdll = uiSizeofdescriptors + uiSizeofoft + uiImprva + dllsize; + obBuffer << (fixEntries ? dwPdll : m_vNewiid[i].impdesc.Name); + obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.FirstThunk); + + dllsize += static_cast(m_vNewiid[i].name.size()) + 1; + } + + obBuffer << (dword)0; + obBuffer << (dword)0; + obBuffer << (dword)0; + obBuffer << (dword)0; + obBuffer << (dword)0; + + unsigned int uiPfunc = uiSizeofdescriptors + uiSizeofoft + uiSizeofdllnames + uiImprva; + + // Rebuild original first thunk + for (unsigned int i=0;i::IMAGE_ORDINAL_FLAG + || fixEntries == false) + { + obBuffer << m_vNewiid[i].originalfirstthunk[j].itd.Ordinal; + } + else + { + obBuffer << uiPfunc; + } + uiPfunc += static_cast(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3; + } + obBuffer << (dword)0; + } + + // Write dllnames into import directory + for (unsigned int i=0;i(m_vNewiid[i].name.size())+1); + } + + // Write function names into directory + for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 1); + } + } + } + + /** + * Removes a specific file and all functions of it from the import directory. + * @param strFilename Name of the file which will be removed. + **/ + template + int ImportDirectory::removeFile(const std::string& strFilename) + { + unsigned int oldSize = static_cast(m_vNewiid.size()); + + m_vNewiid.erase(std::remove_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)), m_vNewiid.end()); + + return oldSize == m_vNewiid.size() ? 1 : 0; + } + + /** + * Removes a specific function from the import directory. + * @param strFilename Name of the file which exports the function. + * @param strFuncname Name of the imported function. + **/ + template + int ImportDirectory::removeFunction(const std::string& strFilename, const std::string& strFuncname) + { + ImpDirFileIterator viPos = m_vNewiid.begin(); + + int notFound = 1; + + while (viPos != m_vNewiid.end()) + { + if (isEqualNc(viPos->name, strFilename)) + { + unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); + viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(&PELIB_THUNK_DATA::equalFunctionName), strFuncname)), viPos->originalfirstthunk.end()); + //viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(CompPolicy(), strFuncname))); + if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; + } + ++viPos; + } + + return notFound; + } + + /** + * Removes a specific function from the import directory. + * @param strFilename Name of the file which exports the function. + * @param wHint The hint of the function. + **/ + template + int ImportDirectory::removeFunction(const std::string& strFilename, word wHint) + { + ImpDirFileIterator viPos = m_vNewiid.begin(); + int notFound = 1; + + while (viPos != m_vNewiid.end()) + { + if (isEqualNc(viPos->name, strFilename)) + { + unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); + viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(&PELIB_THUNK_DATA::equalHint), wHint)), viPos->originalfirstthunk.end()); + unsigned int newPos = static_cast(viPos->originalfirstthunk.size()); + if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; + } + ++viPos; + } + + return notFound; + } + + /** + * Writes the current import directory to a file. + * @param strFilename Name of the file. + * @param uiOffset File Offset of the new import directory. + * @param uiRva RVA which belongs to that file offset. + **/ + template + int ImportDirectory::write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) + { + 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(uiOffset, std::ios_base::beg); + + std::vector vBuffer; + + rebuild(vBuffer, uiRva); + + ofFile.write(reinterpret_cast(&vBuffer[0]), vBuffer.size()); + ofFile.close(); + + std::copy(m_vNewiid.begin(), m_vNewiid.end(), std::back_inserter(m_vOldiid)); + m_vNewiid.clear(); + + return NO_ERROR; + } + + /** + * Returns the size of the import directory. + * @return Size of the import directory. + **/ + template + unsigned int ImportDirectory::size() const + { + // Only the descriptors of m_vOldiid must be rebuilt, not the data they point to. + return std::accumulate(m_vNewiid.begin(), m_vNewiid.end(), 0, accumulate >) + + (m_vOldiid.size() + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size(); + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return FirstThunk value of an imported file. + **/ + template + dword ImportDirectory::getFirstThunk(const std::string& strFilename, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; + } + else + { + return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return OriginalFirstThunk value of an imported file. + **/ + template + dword ImportDirectory::getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; + } + else + { + return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return ForwarderChain value of an imported file. + **/ + template + dword ImportDirectory::getForwarderChain(const std::string& strFilename, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; + } + else + { + return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return TimeDateStamp value of an imported file. + **/ + template + dword ImportDirectory::getTimeDateStamp(const std::string& strFilename, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; + } + else + { + return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; + } + } + + template + dword ImportDirectory::getRvaOfName(const std::string& strFilename, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.Name; + } + else + { + return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.Name; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return FirstThunk value of an imported file. + **/ + template + dword ImportDirectory::getFirstThunk(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[dwFilenr].impdesc.FirstThunk; + } + else + { + return m_vNewiid[dwFilenr].impdesc.FirstThunk; + } + } + + template + void ImportDirectory::setFirstThunk(dword dwFilenr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) + { + m_vOldiid[dwFilenr].impdesc.FirstThunk = value; + } + else + { + m_vNewiid[dwFilenr].impdesc.FirstThunk = value; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return OriginalFirstThunk value of an imported file. + **/ + template + dword ImportDirectory::getOriginalFirstThunk(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk; + } + else + { + return m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk; + } + } + + template + void ImportDirectory::setOriginalFirstThunk(dword dwFilenr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) + { + m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk = value; + } + else + { + m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk = value; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return ForwarderChain value of an imported file. + **/ + template + dword ImportDirectory::getForwarderChain(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[dwFilenr].impdesc.ForwarderChain; + } + else + { + return m_vNewiid[dwFilenr].impdesc.ForwarderChain; + } + } + + template + void ImportDirectory::setForwarderChain(dword dwFilenr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) + { + m_vOldiid[dwFilenr].impdesc.ForwarderChain = value; + } + else + { + m_vNewiid[dwFilenr].impdesc.ForwarderChain = value; + } + } + + /** + * @param strFilename Name of the imported file. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return TimeDateStamp value of an imported file. + **/ + template + dword ImportDirectory::getTimeDateStamp(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[dwFilenr].impdesc.TimeDateStamp; + } + else + { + return m_vNewiid[dwFilenr].impdesc.TimeDateStamp; + } + } + + template + void ImportDirectory::setTimeDateStamp(dword dwFilenr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) + { + m_vOldiid[dwFilenr].impdesc.TimeDateStamp = value; + } + else + { + m_vNewiid[dwFilenr].impdesc.TimeDateStamp = value; + } + } + + template + dword ImportDirectory::getRvaOfName(dword dwFilenr, currdir cdDir) const + { + if (cdDir == OLDDIR) + { + return m_vOldiid[dwFilenr].impdesc.Name; + } + else + { + return m_vNewiid[dwFilenr].impdesc.Name; + } + } + + template + void ImportDirectory::setRvaOfName(dword dwFilenr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) + { + m_vOldiid[dwFilenr].impdesc.Name = value; + } + else + { + m_vNewiid[dwFilenr].impdesc.Name = value; + } + } + + /** + * @param dwFilenr ID of the imported file. + * @param dwFuncnr ID of the imported function. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return FirstThunk value of an imported function. + **/ + template + dword ImportDirectory::getFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const + { + if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; + else return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; + } + + template + void ImportDirectory::setFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value; + else m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value; + } + + /** + * @param dwFilenr ID of the imported file. + * @param dwFuncnr ID of the imported function. + * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @return OriginalFirstThunk value of an imported function. + **/ + template + dword ImportDirectory::getOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const + { + if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; + else return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; + } + + template + void ImportDirectory::setOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value) + { + if (cdDir == OLDDIR) m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; + else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; + } + + typedef ImportDirectory<32> ImportDirectory32; + typedef ImportDirectory<64> ImportDirectory64; +} + +#endif -- cgit v1.2.3