/* * ResourceDirectory.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. */ #include "ResourceDirectory.h" namespace PeLib { // -------------------------------------------------- ResourceChild ------------------------------------------- ResourceChild::ResourceChild() { } ResourceChild::ResourceChild(const ResourceChild& rhs) { if (dynamic_cast(rhs.child)) { ResourceNode* oldnode = static_cast(rhs.child); entry = rhs.entry; child = new ResourceNode; child->uiElementRva = rhs.child->getElementRva(); static_cast(child)->header = oldnode->header; static_cast(child)->children = oldnode->children; } else { ResourceLeaf* oldnode = static_cast(rhs.child); child = new ResourceLeaf; child->uiElementRva = rhs.child->getElementRva(); static_cast(child)->m_data = oldnode->m_data; static_cast(child)->entry = oldnode->entry; } } ResourceChild& ResourceChild::operator=(const ResourceChild& rhs) { if (this != &rhs) { if (dynamic_cast(rhs.child)) { ResourceNode* oldnode = static_cast(rhs.child); entry = rhs.entry; child = new ResourceNode; child->uiElementRva = rhs.child->getElementRva(); static_cast(child)->header = oldnode->header; static_cast(child)->children = oldnode->children; } else { ResourceLeaf* oldnode = static_cast(rhs.child); child = new ResourceLeaf; child->uiElementRva = rhs.child->getElementRva(); static_cast(child)->m_data = oldnode->m_data; static_cast(child)->entry = oldnode->entry; } } return *this; } ResourceChild::~ResourceChild() { delete child; } /** * Compares the resource child's id to the parameter dwId. * @param dwId ID of a resource. * @return True, if the resource child's id equals the parameter. **/ bool ResourceChild::equalId(dword dwId) const { return entry.irde.Name == dwId; } /** * Compares the resource child's name to the parameter strName. * @param strName ID of a resource. * @return True, if the resource child's name equals the parameter. **/ bool ResourceChild::equalName(std::string strName) const { return entry.wstrName == strName; } /** * Returns true if the resource was given a name. **/ bool ResourceChild::isNamedResource() const { return entry.wstrName.size() != 0; } /** * The children of a resource must be ordered in a certain way. First come the named resources * in sorted order, afterwards followed the unnamed resources in sorted order. **/ bool ResourceChild::operator<(const ResourceChild& rc) const { if (this->isNamedResource() && !rc.isNamedResource()) { return true; } else if (!this->isNamedResource() && rc.isNamedResource()) { return false; } else if (this->isNamedResource() && rc.isNamedResource()) { return this->entry.wstrName < rc.entry.wstrName; } else { return this->entry.irde.Name < rc.entry.irde.Name; } } /* unsigned int ResourceChild::size() const { return PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY::size() + child->size() + (entry.wstrName.size() ? entry.wstrName.size() + 2 : 0); } */ // -------------------------------------------------- ResourceElement ------------------------------------------- /** * Returns the RVA of a ResourceElement. This is the RVA where the ResourceElement can be * found in the file. * @return RVA of the ResourceElement. **/ unsigned int ResourceElement::getElementRva() const { return uiElementRva; } // -------------------------------------------------- ResourceLeaf ------------------------------------------- /** * Checks if a ResourceElement is a leaf or not. * @return Always returns true. **/ bool ResourceLeaf::isLeaf() const { return true; } /** * Reads the next resource leaf from the InputBuffer. * @param inpBuffer An InputBuffer that holds the complete resource directory. * @param uiOffset Offset of the resource leaf that's to be read. * @param uiRva RVA of the beginning of the resource directory. * @param pad Used for debugging purposes. **/ int ResourceLeaf::read(InputBuffer& inpBuffer, unsigned int uiOffset, unsigned int uiRva/*, const std::string& pad*/) { // std::cout << pad << "Leaf:" << std::endl; // Invalid leaf. if (uiOffset + PELIB_IMAGE_RESOURCE_DATA_ENTRY::size() > inpBuffer.size()) { return 1; } uiElementRva = uiOffset + uiRva; inpBuffer.set(uiOffset); inpBuffer >> entry.OffsetToData; inpBuffer >> entry.Size; inpBuffer >> entry.CodePage; inpBuffer >> entry.Reserved; /* std::cout << pad << std::hex << "Offset: " << entry.OffsetToData << std::endl; std::cout << pad << std::hex << "Size: " << entry.Size << std::endl; std::cout << pad << std::hex << "CodePage: " << entry.CodePage << std::endl; std::cout << pad << std::hex << "Reserved: " << entry.Reserved << std::endl; */ // Invalid leaf. if (entry.OffsetToData - uiRva + entry.Size > inpBuffer.size()) { // std::cout << entry.OffsetToData << " XXX " << uiRva << " - " << entry.Size << " - " << inpBuffer.size() << std::endl; return 1; } // std::cout << entry.OffsetToData << " - " << uiRva << " - " << entry.Size << " - " << inpBuffer.size() << std::endl; inpBuffer.set(entry.OffsetToData - uiRva); m_data.assign(inpBuffer.data() + inpBuffer.get(), inpBuffer.data() + inpBuffer.get() + entry.Size); // std::cout << pad << std::hex << "Vector: " << m_data.size() << std::endl; // std::copy(m_data.begin(), m_data.end(), std::ostream_iterator(std::cout << std::hex, " ")); return 0; } /** * Rebuilds the current resource leaf. * @param obBuffer OutputBuffer where the rebuilt resource leaf is stored. * @param uiOffset Offset of the resource leaf inside the resource directory. * @param uiRva RVA of the resource directory. **/ void ResourceLeaf::rebuild(OutputBuffer& obBuffer, unsigned int& uiOffset, unsigned int uiRva, const std::string&) const { // std::cout << std::hex << pad << "Leaf: " << uiOffset << std::endl; uiOffset += PELIB_IMAGE_RESOURCE_DATA_ENTRY::size(); // obBuffer << entry.OffsetToData; // obBuffer << uiOffset; obBuffer << uiRva + uiOffset + (uiOffset % 4); obBuffer << entry.Size; obBuffer << entry.CodePage; obBuffer << entry.Reserved; while (uiOffset % 4) { uiOffset++; obBuffer << (byte)0; } uiOffset += static_cast(m_data.size()); for (unsigned int i=0;i(m_data.size()); } /* /// Returns the size of a resource leaf. unsigned int ResourceLeaf::size() const { return PELIB_IMAGE_RESOURCE_DATA_ENTRY::size() + m_data.size(); } */ /** * Returns a vector that contains the raw data of a resource leaf. * @return Raw data of the resource. **/ std::vector ResourceLeaf::getData() const { return m_data; } /** * Overwrites the raw data of a resource. * @param vData New data of the resource. **/ void ResourceLeaf::setData(const std::vector& vData) { m_data = vData; } /** * Returns the leaf's OffsetToData value. That's the RVA where the raw data of the resource * can be found. * @return The leaf's OffsetToData value. **/ dword ResourceLeaf::getOffsetToData() const { return entry.OffsetToData; } /** * Returns the leaf's Size value. That's the size of the raw data of the resource. * @return The leaf's Size value. **/ dword ResourceLeaf::getSize() const { return entry.Size; } /** * Returns the leaf's CodePage value. * @return The leaf's CodePage value. **/ dword ResourceLeaf::getCodePage() const { return entry.CodePage; } /** * Returns the leaf's Reserved value. * @return The leaf's Reserved value. **/ dword ResourceLeaf::getReserved() const { return entry.Reserved; } /** * Sets the leaf's OffsetToData value. * @param dwValue The leaf's new OffsetToData value. **/ void ResourceLeaf::setOffsetToData(dword dwValue) { entry.OffsetToData = dwValue; } /** * Sets the leaf's Size value. * @param dwValue The leaf's new Size value. **/ void ResourceLeaf::setSize(dword dwValue) { entry.Size = dwValue; } /** * Sets the leaf's CodePage value. * @param dwValue The leaf's new CodePage value. **/ void ResourceLeaf::setCodePage(dword dwValue) { entry.CodePage = dwValue; } /** * Sets the leaf's Reserved value. * @param dwValue The leaf's new Reserved value. **/ void ResourceLeaf::setReserved(dword dwValue) { entry.Reserved = dwValue; } // -------------------------------------------------- ResourceNode ------------------------------------------- /** * Checks if a ResourceElement is a leaf or not. * @return Always returns false. **/ bool ResourceNode::isLeaf() const { return false; } /** * Sorts the node's children and corrects the node's header. **/ void ResourceNode::makeValid() { std::sort(children.begin(), children.end()); header.NumberOfNamedEntries = static_cast(std::count_if(children.begin(), children.end(), std::mem_fun_ref(&ResourceChild::isNamedResource))); header.NumberOfIdEntries = static_cast(children.size()) - header.NumberOfNamedEntries; } /** * Rebuilds the current resource node. * @param obBuffer OutputBuffer where the rebuilt resource node is stored. * @param uiOffset Offset of the resource node inside the resource directory. * @param uiRva RVA of the resource directory. * @param pad Used for debugging. **/ void ResourceNode::rebuild(OutputBuffer& obBuffer, unsigned int& uiOffset, unsigned int uiRva, const std::string& pad) const { /* std::cout << std::hex << pad << uiOffset << std::endl; std::cout << std::hex << pad << "header.Characteristics: " << header.Characteristics << std::endl; std::cout << std::hex << pad << "header.TimeDateStamp: " << header.TimeDateStamp << std::endl; std::cout << std::hex << pad << "header.MajorVersion: " << header.MajorVersion << std::endl; std::cout << std::hex << pad << "header.MinorVersion: " << header.MinorVersion << std::endl; std::cout << std::hex << pad << "header.NumberOfNamedEntries: " << header.NumberOfNamedEntries << std::endl; std::cout << std::hex << pad << "header.NumberOfIdEntries: " << header.NumberOfIdEntries << std::endl; */ obBuffer << header.Characteristics; obBuffer << header.TimeDateStamp; obBuffer << header.MajorVersion; obBuffer << header.MinorVersion; //std::cout << pad << "Children: " << children.size() << std::endl; //std::cout << pad << std::count_if(children.begin(), children.end(), std::mem_fun_ref(&ResourceChild::isNamedResource)) << std::endl; //std::cout << pad << children.size() - std::count_if(children.begin(), children.end(), std::mem_fun_ref(&ResourceChild::isNamedResource)) << std::endl; // obBuffer << std::count_if(children.begin(), children.end(), std::mem_fun_ref(&ResourceChild::isNamedResource)); // obBuffer << children.size() - std::count_if(children.begin(), children.end(), std::mem_fun_ref(&ResourceChild::isNamedResource)); obBuffer << header.NumberOfNamedEntries; obBuffer << header.NumberOfIdEntries; uiOffset += PELIB_IMAGE_RESOURCE_DIRECTORY::size(); for (unsigned int i=0;irebuild(obBuffer, newoffs, uiRva, pad + " "); } uiOffset = newoffs; } /** * Reads the next resource node from the InputBuffer. * @param inpBuffer An InputBuffer that holds the complete resource directory. * @param uiOffset Offset of the resource node that's to be read. * @param uiRva RVA of the beginning of the resource directory. * @param pad Something I need for debugging. Will be removed soon. **/ int ResourceNode::read(InputBuffer& inpBuffer, unsigned int uiOffset, unsigned int uiRva/*, const std::string& pad*/) { // Not enough space to be a valid node. if (uiOffset + PELIB_IMAGE_RESOURCE_DIRECTORY::size() > inpBuffer.size()) { return 1; } uiElementRva = uiOffset + uiRva; inpBuffer.set(uiOffset); inpBuffer >> header.Characteristics; inpBuffer >> header.TimeDateStamp; inpBuffer >> header.MajorVersion; inpBuffer >> header.MinorVersion; inpBuffer >> header.NumberOfNamedEntries; inpBuffer >> header.NumberOfIdEntries; // Not enough space to be a valid node. if (uiOffset + PELIB_IMAGE_RESOURCE_DIRECTORY::size() + (header.NumberOfNamedEntries + header.NumberOfIdEntries) * PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY::size() > inpBuffer.size()) { return 1; } // std::cout << std::hex << pad << "Characteristics: " << header.Characteristics << std::endl; // std::cout << std::hex << pad << "TimeDateStamp: " << header.TimeDateStamp << std::endl; // std::cout << std::hex << pad << "MajorVersion: " << header.MajorVersion << std::endl; // std::cout << std::hex << pad << "MinorVersion: " << header.MinorVersion << std::endl; // std::cout << std::hex << pad << "NumberOfNamedEntries: " << header.NumberOfNamedEntries << std::endl; // std::cout << std::hex << pad << "NumberOfIdEntries: " << header.NumberOfIdEntries << std::endl; for (int i=0;i> rc.entry.irde.Name; inpBuffer >> rc.entry.irde.OffsetToData; unsigned int lastPos = inpBuffer.get(); if (rc.entry.irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING) { // Enough space to read string length? if ((rc.entry.irde.Name & ~PELIB_IMAGE_RESOURCE_NAME_IS_STRING) + 2 < inpBuffer.size()) { inpBuffer.set(rc.entry.irde.Name & ~PELIB_IMAGE_RESOURCE_NAME_IS_STRING); word strlen; inpBuffer >> strlen; // Enough space to read string? if ((rc.entry.irde.Name & ~PELIB_IMAGE_RESOURCE_NAME_IS_STRING) + 2 * strlen < inpBuffer.size()) { wchar_t c; for (word i=0;i> c; rc.entry.wstrName += c; } } } // std::wcout << rc.entry.wstrName << std::endl; // std::cout << strlen << std::endl; inpBuffer.set(lastPos); } if (rc.entry.irde.OffsetToData & PELIB_IMAGE_RESOURCE_DATA_IS_DIRECTORY) { rc.child = new ResourceNode; rc.child->read(inpBuffer, rc.entry.irde.OffsetToData & ~PELIB_IMAGE_RESOURCE_DATA_IS_DIRECTORY, uiRva/*, pad + " "*/); } else { rc.child = new ResourceLeaf; rc.child->read(inpBuffer, rc.entry.irde.OffsetToData, uiRva/*, pad + " "*/); } // std::cout << std::hex << pad << "Entry " << i << "(Name): " << rc.entry.irde.Name << std::endl; // std::cout << std::hex << pad << "Entry " << i << "(Offset): " << rc.entry.irde.OffsetToData << std::endl; children.push_back(rc); inpBuffer.set(lastPos); } return 0; } /** * Returns the number of children of the current node. Note that this number is the number * of defined children, not the value from the header. * @return Number of node's children. **/ unsigned int ResourceNode::getNumberOfChildren() const { return static_cast(children.size()); } /** * Adds another child to the current node. **/ void ResourceNode::addChild() { ResourceChild c; c.child = 0; children.push_back(c); } /** * Returns a node's child. * @param uiIndex Index of the child. * @return The child identified by uiIndex. This child can be either a ResourceNode or a ResourceLeaf. **/ ResourceElement* ResourceNode::getChild(unsigned int uiIndex) { return children[uiIndex].child; } /** * Removes a child from the current node. * @param uiIndex Index of the child. **/ void ResourceNode::removeChild(unsigned int uiIndex) { children.erase(children.begin() + uiIndex); } /** * Returns the name of a child. * @param uiIndex Index of the child. * @return Either the name of the specified child or an empty string. **/ std::string ResourceNode::getChildName(unsigned int uiIndex) const { return children[uiIndex].entry.wstrName; } /** * Returns the Name value of a child. * @param uiIndex Index of the child. * @return Name value of a child. **/ dword ResourceNode::getOffsetToChildName(unsigned int uiIndex) const { return children[uiIndex].entry.irde.Name; } /** * Returns the OffsetToData value of a child. * @param uiIndex Index of the child. * @return OffsetToData value of a child. **/ dword ResourceNode::getOffsetToChildData(unsigned int uiIndex) const { return children[uiIndex].entry.irde.OffsetToData; } /** * Sets the name of a child. * @param uiIndex Index of the child. * @param strNewName New name of the resource. **/ void ResourceNode::setChildName(unsigned int uiIndex, const std::string& strNewName) { children[uiIndex].entry.wstrName = strNewName; } /** * Sets the Name value of a child. * @param uiIndex Index of the child. * @param dwNewOffset New Name value of the resource. **/ void ResourceNode::setOffsetToChildName(unsigned int uiIndex, dword dwNewOffset) { children[uiIndex].entry.irde.Name = dwNewOffset; } /** * Sets the OffsetToData value of a child. * @param uiIndex Index of the child. * @param dwNewOffset New OffsetToData value of the resource. **/ void ResourceNode::setOffsetToChildData(unsigned int uiIndex, dword dwNewOffset) { children[uiIndex].entry.irde.OffsetToData = dwNewOffset; } /** * Returns the Characteristics value of the node. * @return Characteristics value of the node. **/ dword ResourceNode::getCharacteristics() const { return header.Characteristics; } /** * Returns the TimeDateStamp value of the node. * @return TimeDateStamp value of the node. **/ dword ResourceNode::getTimeDateStamp() const { return header.TimeDateStamp; } /** * Returns the MajorVersion value of the node. * @return MajorVersion value of the node. **/ word ResourceNode::getMajorVersion() const { return header.MajorVersion; } /** * Returns the MinorVersion value of the node. * @return MinorVersion value of the node. **/ word ResourceNode::getMinorVersion() const { return header.MinorVersion; } /** * Returns the NumberOfNamedEntries value of the node. * @return NumberOfNamedEntries value of the node. **/ word ResourceNode::getNumberOfNamedEntries() const { return header.NumberOfNamedEntries; } /** * Returns the NumberOfIdEntries value of the node. * @return NumberOfIdEntries value of the node. **/ word ResourceNode::getNumberOfIdEntries() const { return header.NumberOfIdEntries; } /** * Sets the Characteristics value of the node. * @param value New Characteristics value of the node. **/ void ResourceNode::setCharacteristics(dword value) { header.Characteristics = value; } /** * Sets the TimeDateStamp value of the node. * @param value New TimeDateStamp value of the node. **/ void ResourceNode::setTimeDateStamp(dword value) { header.TimeDateStamp = value; } /** * Sets the MajorVersion value of the node. * @param value New MajorVersion value of the node. **/ void ResourceNode::setMajorVersion(word value) { header.MajorVersion = value; } /** * Sets the MinorVersion value of the node. * @param value New MinorVersion value of the node. **/ void ResourceNode::setMinorVersion(word value) { header.MinorVersion = value; } /** * Sets the NumberOfNamedEntries value of the node. * @param value New NumberOfNamedEntries value of the node. **/ void ResourceNode::setNumberOfNamedEntries(word value) { header.NumberOfNamedEntries = value; } /** * Sets the NumberOfIdEntries value of the node. * @param value New NumberOfIdEntries value of the node. **/ void ResourceNode::setNumberOfIdEntries(word value) { header.NumberOfIdEntries = value; } /* /// Returns the size of a resource node. unsigned int ResourceNode::size() const { if (children.size()) { std::cout << std::accumulate(children.begin(), children.end(), 0, accumulate) << std::endl; return PELIB_IMAGE_RESOURCE_DIRECTORY::size() + std::accumulate(children.begin(), children.end(), 0, accumulate); } else { return 0; } } */ // -------------------------------------------------- ResourceDirectory ------------------------------------------- /** * Returns the root node of the resource directory. * @return Root node of the resource directory. **/ ResourceNode* ResourceDirectory::getRoot() { return &m_rnRoot; } /** * Correctly sorts the resource nodes of the resource tree. This function should be called * before calling rebuild. **/ void ResourceDirectory::makeValid() { m_rnRoot.makeValid(); } /** * Reads the resource directory from a file. * @param strFilename Name of the file. * @param uiOffset File offset of the resource directory. * @param uiSize Raw size of the resource directory. * @param uiResDirRva RVA of the beginning of the resource directory. **/ int ResourceDirectory::read(const std::string& strFilename, unsigned int uiOffset, unsigned int uiSize, unsigned int uiResDirRva) { if (!uiSize || !uiOffset) { return 1; } std::ifstream ifFile(strFilename.c_str(), std::ios::binary); if (!ifFile) { // throw Exceptions::CannotOpenFile(ResourceDirectoryId, __LINE__); return 1; } if (fileSize(ifFile) < uiOffset + uiSize) { // throw Exceptions::InvalidFormat(ResourceDirectoryId, __LINE__); return 1; } ifFile.seekg(uiOffset, std::ios::beg); PELIB_IMAGE_RESOURCE_DIRECTORY irdCurrRoot; std::vector vResourceDirectory(uiSize); ifFile.read(reinterpret_cast(&vResourceDirectory[0]), uiSize); InputBuffer inpBuffer(vResourceDirectory); // ResourceNode currNode; return m_rnRoot.read(inpBuffer, 0, uiResDirRva/*, ""*/); // std::swap(currNode, m_rnRoot); } /** * Rebuilds the resource directory. * @param vBuffer Buffer the source directory will be written to. * @param uiRva RVA of the resource directory. **/ void ResourceDirectory::rebuild(std::vector& vBuffer, unsigned int uiRva) const { OutputBuffer obBuffer(vBuffer); unsigned int offs = 0; // std::cout << "Root: " << m_rnRoot.children.size() << std::endl; m_rnRoot.rebuild(obBuffer, offs, uiRva, ""); } /** * Returns the size of the entire rebuilt resource directory. That's the size of the entire * structure as it's written back to a file. **/ /* unsigned int ResourceDirectory::size() const { return m_rnRoot.size(); } */ /** * Writes the current resource directory back into a file. * @param strFilename Name of the output file. * @param uiOffset File offset where the resource directory will be written to. * @param uiRva RVA of the file offset. **/ int ResourceDirectory::write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) 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(uiOffset, std::ios::beg); std::vector vBuffer; rebuild(vBuffer, uiRva); ofFile.write(reinterpret_cast(&vBuffer[0]), static_cast(vBuffer.size())); ofFile.close(); return 0; } /** * Adds another resource type. The new resource type is identified by the ID dwResTypeId. * @param dwResTypeId ID which identifies the resource type. **/ int ResourceDirectory::addResourceType(dword dwResTypeId) { std::vector::iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalId), dwResTypeId)); if (Iter != m_rnRoot.children.end()) { return 1; // throw Exceptions::EntryAlreadyExists(ResourceDirectoryId, __LINE__); } ResourceChild rcCurr; rcCurr.child = new ResourceNode; rcCurr.entry.irde.Name = dwResTypeId; m_rnRoot.children.push_back(rcCurr); return 0; } /** * Adds another resource type. The new resource type is identified by the name strResTypeName. * @param strResTypeName Name which identifies the resource type. **/ int ResourceDirectory::addResourceType(const std::string& strResTypeName) { std::vector::iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalName), strResTypeName)); if (Iter != m_rnRoot.children.end()) { return 1; // throw Exceptions::EntryAlreadyExists(ResourceDirectoryId, __LINE__); } ResourceChild rcCurr; rcCurr.entry.wstrName = strResTypeName; rcCurr.child = new ResourceNode; m_rnRoot.children.push_back(rcCurr); return 0; } /** * Removes the resource type identified by the ID dwResTypeId. * @param dwResTypeId ID which identifies the resource type. **/ int ResourceDirectory::removeResourceType(dword dwResTypeId) { std::vector::iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalId), dwResTypeId)); if (Iter == m_rnRoot.children.end()) { return 1; // throw Exceptions::ResourceTypeDoesNotExist(ResourceDirectoryId, __LINE__); } bool isNamed = false; if (Iter->isNamedResource()) isNamed = true; m_rnRoot.children.erase(Iter); if (isNamed) m_rnRoot.header.NumberOfNamedEntries = static_cast(m_rnRoot.children.size()); else m_rnRoot.header.NumberOfIdEntries = static_cast(m_rnRoot.children.size()); return 0; } /** * Removes the resource type identified by the name strResTypeName. * @param strResTypeName Name which identifies the resource type. **/ int ResourceDirectory::removeResourceType(const std::string& strResTypeName) { std::vector::iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalName), strResTypeName)); if (Iter == m_rnRoot.children.end()) { return 1; // throw Exceptions::ResourceTypeDoesNotExist(ResourceDirectoryId, __LINE__); } bool isNamed = false; if (Iter->isNamedResource()) isNamed = true; m_rnRoot.children.erase(Iter); if (isNamed) m_rnRoot.header.NumberOfNamedEntries = static_cast(m_rnRoot.children.size()); else m_rnRoot.header.NumberOfIdEntries = static_cast(m_rnRoot.children.size()); return 0; } /** * Removes the resource type identified by the index uiIndex. * @param uiIndex Index which identifies the resource type. **/ int ResourceDirectory::removeResourceTypeByIndex(unsigned int uiIndex) { bool isNamed = false; if (m_rnRoot.children[uiIndex].isNamedResource()) isNamed = true; m_rnRoot.children.erase(m_rnRoot.children.begin() + uiIndex); if (isNamed) m_rnRoot.header.NumberOfNamedEntries = static_cast(m_rnRoot.children.size()); else m_rnRoot.header.NumberOfIdEntries = static_cast(m_rnRoot.children.size()); return 0; } /** * Adds another resource to the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param dwResTypeId ID of the resource type. * @param dwResId ID of the resource. **/ int ResourceDirectory::addResource(dword dwResTypeId, dword dwResId) { ResourceChild rcCurr; rcCurr.entry.irde.Name = dwResId; return addResourceT(dwResTypeId, dwResId, rcCurr); } /** * Adds another resource to the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param dwResTypeId ID of the resource type. * @param strResName Name of the resource. **/ int ResourceDirectory::addResource(dword dwResTypeId, const std::string& strResName) { ResourceChild rcCurr; rcCurr.entry.wstrName = strResName; return addResourceT(dwResTypeId, strResName, rcCurr); } /** * Adds another resource to the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param strResTypeName Name of the resource type. * @param dwResId ID of the resource. **/ int ResourceDirectory::addResource(const std::string& strResTypeName, dword dwResId) { ResourceChild rcCurr; rcCurr.entry.irde.Name = dwResId; return addResourceT(strResTypeName, dwResId, rcCurr); } /** * Adds another resource to the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param strResTypeName Name of the resource type. * @param strResName Name of the resource. **/ int ResourceDirectory::addResource(const std::string& strResTypeName, const std::string& strResName) { ResourceChild rcCurr; rcCurr.entry.wstrName = strResName; return addResourceT(strResTypeName, strResName, rcCurr); } /** * Removes a resource from the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param dwResTypeIndex ID of the resource type. * @param dwResId ID of the resource. **/ int ResourceDirectory::removeResource(dword dwResTypeIndex, dword dwResId) { return removeResourceT(dwResTypeIndex, dwResId); } /** * Removes a resource from the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param dwResTypeIndex ID of the resource type. * @param strResName Name of the resource. **/ int ResourceDirectory::removeResource(dword dwResTypeIndex, const std::string& strResName) { return removeResourceT(dwResTypeIndex, strResName); } /** * Removes a resource from the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param strResTypeName Name of the resource type. * @param dwResId ID of the resource. **/ int ResourceDirectory::removeResource(const std::string& strResTypeName, dword dwResId) { return removeResourceT(strResTypeName, dwResId); } /** * Removes a resource from the resource tree. The first parameter identifies the resource type * of the new resource, the second parameter identifies the resource itself. * @param strResTypeName Name of the resource type. * @param strResName Name of the resource. **/ int ResourceDirectory::removeResource(const std::string& strResTypeName, const std::string& strResName) { return removeResourceT(strResTypeName, strResName); } /** * Returns the number of resource types. **/ unsigned int ResourceDirectory::getNumberOfResourceTypes() const { return static_cast(m_rnRoot.children.size()); } /** * Returns the ID of a resource type which was specified through an index. * The valid range of the parameter uiIndex is 0...getNumberOfResourceTypes() - 1. * Leaving the invalid range leads to undefined behaviour. * @param uiIndex Index which identifies a resource type. * @return The ID of the specified resource type. **/ dword ResourceDirectory::getResourceTypeIdByIndex(unsigned int uiIndex) const { return m_rnRoot.children[uiIndex].entry.irde.Name; } /** * Returns the name of a resource type which was specified through an index. * The valid range of the parameter uiIndex is 0...getNumberOfResourceTypes() - 1. * Leaving the invalid range leads to undefined behaviour. * @param uiIndex Index which identifies a resource type. * @return The name of the specified resource type. **/ std::string ResourceDirectory::getResourceTypeNameByIndex(unsigned int uiIndex) const { return m_rnRoot.children[uiIndex].entry.wstrName; } /** * Converts the ID of a resource type to an index. * @param dwResTypeId ID of the resource type. * @return Index of that resource type. **/ int ResourceDirectory::resourceTypeIdToIndex(dword dwResTypeId) const { std::vector::const_iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalId), dwResTypeId)); if (Iter == m_rnRoot.children.end()) return -1; return static_cast(std::distance(m_rnRoot.children.begin(), Iter)); } /** * Converts the name of a resource type to an index. * @param strResTypeName ID of the resource type. * @return Index of that resource type. **/ int ResourceDirectory::resourceTypeNameToIndex(const std::string& strResTypeName) const { std::vector::const_iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalName), strResTypeName)); if (Iter == m_rnRoot.children.end()) return -1; return static_cast(std::distance(m_rnRoot.children.begin(), Iter)); } /** * Returns the number of resources of a specific resource type. * @param dwId ID of the resource type. * @return Number of resources of resource type dwId. **/ unsigned int ResourceDirectory::getNumberOfResources(dword dwId) const { // std::vector::const_iterator IterD = m_rnRoot.children.begin(); // std::cout << dwId << std::endl; // while (IterD != m_rnRoot.children.end()) // { // std::cout << IterD->entry.irde.Name << std::endl; // ++IterD; // } std::vector::const_iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalId), dwId)); if (Iter == m_rnRoot.children.end()) { return 0xFFFFFFFF; } else { ResourceNode* currNode = static_cast(Iter->child); return static_cast(currNode->children.size()); } } /** * Returns the number of resources of a specific resource type. * @param strResTypeName Name of the resource type. * @return Number of resources of resource type strResTypeName. **/ unsigned int ResourceDirectory::getNumberOfResources(const std::string& strResTypeName) const { std::vector::const_iterator Iter = std::find_if(m_rnRoot.children.begin(), m_rnRoot.children.end(), std::bind2nd(std::mem_fun_ref(&ResourceChild::equalName), strResTypeName)); if (Iter == m_rnRoot.children.end()) { return 0xFFFFFFFF; } else { ResourceNode* currNode = static_cast(Iter->child); return static_cast(currNode->children.size()); } } /** * Returns the number of resources of a resource type which was specified through an index. * The valid range of the parameter uiIndex is 0...getNumberOfResourceTypes() - 1. * Leaving the invalid range leads to undefined behaviour. * @param uiIndex Index which identifies a resource type. * @return The number of resources of the specified resource type. **/ unsigned int ResourceDirectory::getNumberOfResourcesByIndex(unsigned int uiIndex) const { ResourceNode* currNode = static_cast(m_rnRoot.children[uiIndex].child); return static_cast(currNode->children.size()); } /** * Gets the resource data of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param data Vector where the data is stored. **/ void ResourceDirectory::getResourceData(dword dwResTypeId, dword dwResId, std::vector& data) const { getResourceDataT(dwResTypeId, dwResId, data); } /** * Gets the resource data of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param data Vector where the data is stored. **/ void ResourceDirectory::getResourceData(dword dwResTypeId, const std::string& strResName, std::vector& data) const { getResourceDataT(dwResTypeId, strResName, data); } /** * Gets the resource data of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param data Vector where the data is stored. **/ void ResourceDirectory::getResourceData(const std::string& strResTypeName, dword dwResId, std::vector& data) const { getResourceDataT(strResTypeName, dwResId, data); } /** * Gets the resource data of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param data Vector where the data is stored. **/ void ResourceDirectory::getResourceData(const std::string& strResTypeName, const std::string& strResName, std::vector& data) const { getResourceDataT(strResTypeName, strResName, data); } /** * Gets the resource data of a specific resource by index. * The valid range of the parameter uiResTypeIndex is 0...getNumberOfResourceTypes() - 1. * The valid range of the parameter uiResIndex is 0...getNumberOfResources() - 1. * Leaving the invalid range leads to undefined behaviour. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @param data Vector where the data is stored. **/ void ResourceDirectory::getResourceDataByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, std::vector& data) const { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); currNode = static_cast(currNode->children[uiResIndex].child); ResourceLeaf* currLeaf = static_cast(currNode->children[0].child); data.assign(currLeaf->m_data.begin(), currLeaf->m_data.end()); } /** * Sets the resource data of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param data The new resource data. **/ void ResourceDirectory::setResourceData(dword dwResTypeId, dword dwResId, std::vector& data) { setResourceDataT(dwResTypeId, dwResId, data); } /** * Sets the resource data of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param data The new resource data. **/ void ResourceDirectory::setResourceData(dword dwResTypeId, const std::string& strResName, std::vector& data) { setResourceDataT(dwResTypeId, strResName, data); } /** * Sets the resource data of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param data The new resource data. **/ void ResourceDirectory::setResourceData(const std::string& strResTypeName, dword dwResId, std::vector& data) { setResourceDataT(strResTypeName, dwResId, data); } /** * Sets the resource data of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param data The new resource data. **/ void ResourceDirectory::setResourceData(const std::string& strResTypeName, const std::string& strResName, std::vector& data) { setResourceDataT(strResTypeName, strResName, data); } /** * Sets the resource data of a specific resource by index. * The valid range of the parameter uiResTypeIndex is 0...getNumberOfResourceTypes() - 1. * The valid range of the parameter uiResIndex is 0...getNumberOfResources() - 1. * Leaving the invalid range leads to undefined behaviour. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @param data The new resource data. **/ void ResourceDirectory::setResourceDataByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, std::vector& data) { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); currNode = static_cast(currNode->children[uiResIndex].child); ResourceLeaf* currLeaf = static_cast(currNode->children[0].child); currLeaf->m_data.assign(data.begin(), data.end()); } /** * Gets the ID of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param strResName Identifies the resource. * @return ID of the specified resource. **/ dword ResourceDirectory::getResourceId(dword dwResTypeId, const std::string& strResName) const { return getResourceIdT(dwResTypeId, strResName); } /** * Gets the ID of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param strResName Identifies the resource. * @return ID of the specified resource. **/ dword ResourceDirectory::getResourceId(const std::string& strResTypeName, const std::string& strResName) const { return getResourceIdT(strResTypeName, strResName); } /** * Gets the ID of a specific resource by index. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @return ID of the specified resource. **/ dword ResourceDirectory::getResourceIdByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex) const { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); return currNode->children[uiResIndex].entry.irde.Name; } /** * Sets the ID of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param dwNewResId New ID of the resource. **/ void ResourceDirectory::setResourceId(dword dwResTypeId, dword dwResId, dword dwNewResId) { setResourceIdT(dwResTypeId, dwResId, dwNewResId); } /** * Sets the ID of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param dwNewResId New ID of the resource. **/ void ResourceDirectory::setResourceId(dword dwResTypeId, const std::string& strResName, dword dwNewResId) { setResourceIdT(dwResTypeId, strResName, dwNewResId); } /** * Sets the ID of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param dwNewResId New ID of the resource. **/ void ResourceDirectory::setResourceId(const std::string& strResTypeName, dword dwResId, dword dwNewResId) { setResourceIdT(strResTypeName, dwResId, dwNewResId); } /** * Sets the ID of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param dwNewResId New ID of the resource. **/ void ResourceDirectory::setResourceId(const std::string& strResTypeName, const std::string& strResName, dword dwNewResId) { setResourceIdT(strResTypeName, strResName, dwNewResId); } /** * Sets the ID of a specific resource by index. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @param dwNewResId New ID of the specified resource. **/ void ResourceDirectory::setResourceIdByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, dword dwNewResId) { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); currNode->children[uiResIndex].entry.irde.Name = dwNewResId; } /** * Gets the Name of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @return Name of the specified resource. **/ std::string ResourceDirectory::getResourceName(dword dwResTypeId, dword dwResId) const { return getResourceNameT(dwResTypeId, dwResId); } /** * Gets the Name of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @return Name of the specified resource. **/ std::string ResourceDirectory::getResourceName(const std::string& strResTypeName, dword dwResId) const { return getResourceNameT(strResTypeName, dwResId); } /** * Gets the name of a specific resource by index. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @return Name of the specified resource. **/ std::string ResourceDirectory::getResourceNameByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex) const { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); return currNode->children[uiResIndex].entry.wstrName; } /** * Sets the name of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param strNewResName New name of the specified resource. **/ void ResourceDirectory::setResourceName(dword dwResTypeId, dword dwResId, const std::string& strNewResName) { setResourceNameT(dwResTypeId, dwResId, strNewResName); } /** * Sets the name of a specific resource. * @param dwResTypeId Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param strNewResName New name of the specified resource. **/ void ResourceDirectory::setResourceName(dword dwResTypeId, const std::string& strResName, const std::string& strNewResName) { setResourceNameT(dwResTypeId, strResName, strNewResName); } /** * Sets the name of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param dwResId Identifies the resource. * @param strNewResName New name of the specified resource. **/ void ResourceDirectory::setResourceName(const std::string& strResTypeName, dword dwResId, const std::string& strNewResName) { setResourceNameT(strResTypeName, dwResId, strNewResName); } /** * Sets the name of a specific resource. * @param strResTypeName Identifies the resource type of the resource. * @param strResName Identifies the resource. * @param strNewResName New name of the specified resource. **/ void ResourceDirectory::setResourceName(const std::string& strResTypeName, const std::string& strResName, const std::string& strNewResName) { setResourceNameT(strResTypeName, strResName, strNewResName); } /** * Sets the name of a specific resource by index. * @param uiResTypeIndex Identifies the resource type of the resource. * @param uiResIndex Identifies the resource. * @param strNewResName New name of the specified resource. **/ void ResourceDirectory::setResourceNameByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, const std::string& strNewResName) { ResourceNode* currNode = static_cast(m_rnRoot.children[uiResTypeIndex].child); currNode->children[uiResIndex].entry.wstrName = strNewResName; } }