#ifndef LLVM_OBJECT_WINDOWSRESOURCE_H
#define LLVM_OBJECT_WINDOWSRESOURCE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <map>
namespace llvm {
class raw_ostream;
class ScopedPrinter;
namespace object {
class WindowsResource;
class ResourceSectionRef;
struct coff_resource_dir_table;
const size_t WIN_RES_MAGIC_SIZE = 16;
const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
struct WinResHeaderPrefix {
support::ulittle32_t DataSize;
support::ulittle32_t HeaderSize;
};
struct WinResIDs {
uint16_t TypeFlag;
support::ulittle16_t TypeID;
uint16_t NameFlag;
support::ulittle16_t NameID;
void setType(uint16_t ID) {
TypeFlag = 0xffff;
TypeID = ID;
}
void setName(uint16_t ID) {
NameFlag = 0xffff;
NameID = ID;
}
};
struct WinResHeaderSuffix {
support::ulittle32_t DataVersion;
support::ulittle16_t MemoryFlags;
support::ulittle16_t Language;
support::ulittle32_t Version;
support::ulittle32_t Characteristics;
};
class EmptyResError : public GenericBinaryError {
public:
EmptyResError(Twine Msg, object_error ECOverride)
: GenericBinaryError(Msg, ECOverride) {}
};
class ResourceEntryRef {
public:
Error moveNext(bool &End);
bool checkTypeString() const { return IsStringType; }
ArrayRef<UTF16> getTypeString() const { return Type; }
uint16_t getTypeID() const { return TypeID; }
bool checkNameString() const { return IsStringName; }
ArrayRef<UTF16> getNameString() const { return Name; }
uint16_t getNameID() const { return NameID; }
uint16_t getDataVersion() const { return Suffix->DataVersion; }
uint16_t getLanguage() const { return Suffix->Language; }
uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
uint16_t getMinorVersion() const { return Suffix->Version; }
uint32_t getCharacteristics() const { return Suffix->Characteristics; }
ArrayRef<uint8_t> getData() const { return Data; }
private:
friend class WindowsResource;
ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner);
Error loadNext();
static Expected<ResourceEntryRef> create(BinaryStreamRef Ref,
const WindowsResource *Owner);
BinaryStreamReader Reader;
const WindowsResource *Owner;
bool IsStringType;
ArrayRef<UTF16> Type;
uint16_t TypeID;
bool IsStringName;
ArrayRef<UTF16> Name;
uint16_t NameID;
const WinResHeaderSuffix *Suffix = nullptr;
ArrayRef<uint8_t> Data;
};
class WindowsResource : public Binary {
public:
Expected<ResourceEntryRef> getHeadEntry();
static bool classof(const Binary *V) { return V->isWinRes(); }
static Expected<std::unique_ptr<WindowsResource>>
createWindowsResource(MemoryBufferRef Source);
private:
friend class ResourceEntryRef;
WindowsResource(MemoryBufferRef Source);
BinaryByteStream BBS;
};
class WindowsResourceParser {
public:
class TreeNode;
WindowsResourceParser(bool MinGW = false);
Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
Error parse(ResourceSectionRef &RSR, StringRef Filename,
std::vector<std::string> &Duplicates);
void cleanUpManifests(std::vector<std::string> &Duplicates);
void printTree(raw_ostream &OS) const;
const TreeNode &getTree() const { return Root; }
ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
ArrayRef<std::vector<UTF16>> getStringTable() const { return StringTable; }
class TreeNode {
public:
template <typename T>
using Children = std::map<T, std::unique_ptr<TreeNode>>;
void print(ScopedPrinter &Writer, StringRef Name) const;
uint32_t getTreeSize() const;
uint32_t getStringIndex() const { return StringIndex; }
uint32_t getDataIndex() const { return DataIndex; }
uint16_t getMajorVersion() const { return MajorVersion; }
uint16_t getMinorVersion() const { return MinorVersion; }
uint32_t getCharacteristics() const { return Characteristics; }
bool checkIsDataNode() const { return IsDataNode; }
const Children<uint32_t> &getIDChildren() const { return IDChildren; }
const Children<std::string> &getStringChildren() const {
return StringChildren;
}
private:
friend class WindowsResourceParser;
static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
static std::unique_ptr<TreeNode> createIDNode();
static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion,
uint32_t Characteristics,
uint32_t Origin,
uint32_t DataIndex);
explicit TreeNode(uint32_t StringIndex);
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
std::vector<std::vector<uint8_t>> &Data,
std::vector<std::vector<UTF16>> &StringTable,
TreeNode *&Result);
TreeNode &addTypeNode(const ResourceEntryRef &Entry,
std::vector<std::vector<UTF16>> &StringTable);
TreeNode &addNameNode(const ResourceEntryRef &Entry,
std::vector<std::vector<UTF16>> &StringTable);
bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
std::vector<std::vector<uint8_t>> &Data,
TreeNode *&Result);
bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin,
uint32_t DataIndex, TreeNode *&Result);
TreeNode &addIDChild(uint32_t ID);
TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
std::vector<std::vector<UTF16>> &StringTable);
void shiftDataIndexDown(uint32_t Index);
bool IsDataNode = false;
uint32_t StringIndex;
uint32_t DataIndex;
Children<uint32_t> IDChildren;
Children<std::string> StringChildren;
uint16_t MajorVersion = 0;
uint16_t MinorVersion = 0;
uint32_t Characteristics = 0;
uint32_t Origin;
};
struct StringOrID {
bool IsString;
ArrayRef<UTF16> String;
uint32_t ID;
StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
};
private:
Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
const coff_resource_dir_table &Table, uint32_t Origin,
std::vector<StringOrID> &Context,
std::vector<std::string> &Duplicates);
bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
TreeNode Root;
std::vector<std::vector<uint8_t>> Data;
std::vector<std::vector<UTF16>> StringTable;
std::vector<std::string> InputFilenames;
bool MinGW;
};
Expected<std::unique_ptr<MemoryBuffer>>
writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
const WindowsResourceParser &Parser,
uint32_t TimeDateStamp);
void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
} }
#endif