1//===-- WindowsResource.h ---------------------------------------*- C++-*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===---------------------------------------------------------------------===// 9// 10// This file declares the .res file class. .res files are intermediate 11// products of the typical resource-compilation process on Windows. This 12// process is as follows: 13// 14// .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file 15// 16// .rc files are human-readable scripts that list all resources a program uses. 17// 18// They are compiled into .res files, which are a list of the resources in 19// binary form. 20// 21// Finally the data stored in the .res is compiled into a COFF file, where it 22// is organized in a directory tree structure for optimized access by the 23// program during runtime. 24// 25// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx 26// 27//===---------------------------------------------------------------------===// 28 29#ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H 30#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H 31 32#include "llvm/ADT/ArrayRef.h" 33#include "llvm/BinaryFormat/COFF.h" 34#include "llvm/Object/Binary.h" 35#include "llvm/Object/Error.h" 36#include "llvm/Support/BinaryByteStream.h" 37#include "llvm/Support/BinaryStreamReader.h" 38#include "llvm/Support/ConvertUTF.h" 39#include "llvm/Support/Endian.h" 40#include "llvm/Support/Error.h" 41#include "llvm/Support/ScopedPrinter.h" 42 43#include <map> 44 45namespace llvm { 46namespace object { 47 48class WindowsResource; 49 50class ResourceEntryRef { 51public: 52 Error moveNext(bool &End); 53 bool checkTypeString() const { return IsStringType; } 54 ArrayRef<UTF16> getTypeString() const { return Type; } 55 uint16_t getTypeID() const { return TypeID; } 56 bool checkNameString() const { return IsStringName; } 57 ArrayRef<UTF16> getNameString() const { return Name; } 58 uint16_t getNameID() const { return NameID; } 59 uint16_t getLanguage() const { return Suffix->Language; } 60 uint16_t getMajorVersion() const { return Suffix->Version >> 16; } 61 uint16_t getMinorVersion() const { return Suffix->Version; } 62 uint32_t getCharacteristics() const { return Suffix->Characteristics; } 63 ArrayRef<uint8_t> getData() const { return Data; } 64 65private: 66 friend class WindowsResource; 67 68 ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner, 69 Error &Err); 70 71 Error loadNext(); 72 73 struct HeaderSuffix { 74 support::ulittle32_t DataVersion; 75 support::ulittle16_t MemoryFlags; 76 support::ulittle16_t Language; 77 support::ulittle32_t Version; 78 support::ulittle32_t Characteristics; 79 }; 80 81 BinaryStreamReader Reader; 82 bool IsStringType; 83 ArrayRef<UTF16> Type; 84 uint16_t TypeID; 85 bool IsStringName; 86 ArrayRef<UTF16> Name; 87 uint16_t NameID; 88 const HeaderSuffix *Suffix = nullptr; 89 ArrayRef<uint8_t> Data; 90 const WindowsResource *OwningRes = nullptr; 91}; 92 93class WindowsResource : public Binary { 94public: 95 Expected<ResourceEntryRef> getHeadEntry(); 96 97 static bool classof(const Binary *V) { return V->isWinRes(); } 98 99 static Expected<std::unique_ptr<WindowsResource>> 100 createWindowsResource(MemoryBufferRef Source); 101 102private: 103 friend class ResourceEntryRef; 104 105 WindowsResource(MemoryBufferRef Source); 106 107 BinaryByteStream BBS; 108}; 109 110class WindowsResourceParser { 111public: 112 class TreeNode; 113 WindowsResourceParser(); 114 Error parse(WindowsResource *WR); 115 void printTree(raw_ostream &OS) const; 116 const TreeNode &getTree() const { return Root; } 117 const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } 118 const ArrayRef<std::vector<UTF16>> getStringTable() const { 119 return StringTable; 120 } 121 122 class TreeNode { 123 public: 124 template <typename T> 125 using Children = std::map<T, std::unique_ptr<TreeNode>>; 126 127 void print(ScopedPrinter &Writer, StringRef Name) const; 128 uint32_t getTreeSize() const; 129 uint32_t getStringIndex() const { return StringIndex; } 130 uint32_t getDataIndex() const { return DataIndex; } 131 uint16_t getMajorVersion() const { return MajorVersion; } 132 uint16_t getMinorVersion() const { return MinorVersion; } 133 uint32_t getCharacteristics() const { return Characteristics; } 134 bool checkIsDataNode() const { return IsDataNode; } 135 const Children<uint32_t> &getIDChildren() const { return IDChildren; } 136 const Children<std::string> &getStringChildren() const { 137 return StringChildren; 138 } 139 140 private: 141 friend class WindowsResourceParser; 142 143 static uint32_t StringCount; 144 static uint32_t DataCount; 145 146 static std::unique_ptr<TreeNode> createStringNode(); 147 static std::unique_ptr<TreeNode> createIDNode(); 148 static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, 149 uint16_t MinorVersion, 150 uint32_t Characteristics); 151 152 explicit TreeNode(bool IsStringNode); 153 TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, 154 uint32_t Characteristics); 155 156 void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString, 157 bool &IsNewNameString); 158 TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString); 159 TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString); 160 TreeNode &addLanguageNode(const ResourceEntryRef &Entry); 161 TreeNode &addChild(uint32_t ID, bool IsDataNode = false, 162 uint16_t MajorVersion = 0, uint16_t MinorVersion = 0, 163 uint32_t Characteristics = 0); 164 TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString); 165 166 bool IsDataNode = false; 167 uint32_t StringIndex; 168 uint32_t DataIndex; 169 Children<uint32_t> IDChildren; 170 Children<std::string> StringChildren; 171 uint16_t MajorVersion = 0; 172 uint16_t MinorVersion = 0; 173 uint32_t Characteristics = 0; 174 }; 175 176private: 177 TreeNode Root; 178 std::vector<std::vector<uint8_t>> Data; 179 std::vector<std::vector<UTF16>> StringTable; 180}; 181 182Error writeWindowsResourceCOFF(std::unique_ptr<MemoryBuffer> &OutputBuffer, 183 llvm::COFF::MachineTypes MachineType, 184 const WindowsResourceParser &Parser); 185 186} // namespace object 187} // namespace llvm 188 189#endif 190