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 50const size_t WIN_RES_MAGIC_SIZE = 16; 51const size_t WIN_RES_NULL_ENTRY_SIZE = 16; 52const uint32_t WIN_RES_HEADER_ALIGNMENT = 4; 53const uint32_t WIN_RES_DATA_ALIGNMENT = 4; 54const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030; 55 56struct WinResHeaderPrefix { 57 support::ulittle32_t DataSize; 58 support::ulittle32_t HeaderSize; 59}; 60 61// Type and Name may each either be an integer ID or a string. This struct is 62// only used in the case where they are both IDs. 63struct WinResIDs { 64 uint16_t TypeFlag; 65 support::ulittle16_t TypeID; 66 uint16_t NameFlag; 67 support::ulittle16_t NameID; 68 69 void setType(uint16_t ID) { 70 TypeFlag = 0xffff; 71 TypeID = ID; 72 } 73 74 void setName(uint16_t ID) { 75 NameFlag = 0xffff; 76 NameID = ID; 77 } 78}; 79 80struct WinResHeaderSuffix { 81 support::ulittle32_t DataVersion; 82 support::ulittle16_t MemoryFlags; 83 support::ulittle16_t Language; 84 support::ulittle32_t Version; 85 support::ulittle32_t Characteristics; 86}; 87 88class EmptyResError : public GenericBinaryError { 89public: 90 EmptyResError(Twine Msg, object_error ECOverride) 91 : GenericBinaryError(Msg, ECOverride) {} 92}; 93 94class ResourceEntryRef { 95public: 96 Error moveNext(bool &End); 97 bool checkTypeString() const { return IsStringType; } 98 ArrayRef<UTF16> getTypeString() const { return Type; } 99 uint16_t getTypeID() const { return TypeID; } 100 bool checkNameString() const { return IsStringName; } 101 ArrayRef<UTF16> getNameString() const { return Name; } 102 uint16_t getNameID() const { return NameID; } 103 uint16_t getDataVersion() const { return Suffix->DataVersion; } 104 uint16_t getLanguage() const { return Suffix->Language; } 105 uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; } 106 uint16_t getMajorVersion() const { return Suffix->Version >> 16; } 107 uint16_t getMinorVersion() const { return Suffix->Version; } 108 uint32_t getCharacteristics() const { return Suffix->Characteristics; } 109 ArrayRef<uint8_t> getData() const { return Data; } 110 111private: 112 friend class WindowsResource; 113 114 ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner); 115 Error loadNext(); 116 117 static Expected<ResourceEntryRef> create(BinaryStreamRef Ref, 118 const WindowsResource *Owner); 119 120 BinaryStreamReader Reader; 121 bool IsStringType; 122 ArrayRef<UTF16> Type; 123 uint16_t TypeID; 124 bool IsStringName; 125 ArrayRef<UTF16> Name; 126 uint16_t NameID; 127 const WinResHeaderSuffix *Suffix = nullptr; 128 ArrayRef<uint8_t> Data; 129 const WindowsResource *OwningRes = nullptr; 130}; 131 132class WindowsResource : public Binary { 133public: 134 Expected<ResourceEntryRef> getHeadEntry(); 135 136 static bool classof(const Binary *V) { return V->isWinRes(); } 137 138 static Expected<std::unique_ptr<WindowsResource>> 139 createWindowsResource(MemoryBufferRef Source); 140 141private: 142 friend class ResourceEntryRef; 143 144 WindowsResource(MemoryBufferRef Source); 145 146 BinaryByteStream BBS; 147}; 148 149class WindowsResourceParser { 150public: 151 class TreeNode; 152 WindowsResourceParser(); 153 Error parse(WindowsResource *WR); 154 void printTree(raw_ostream &OS) const; 155 const TreeNode &getTree() const { return Root; } 156 const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } 157 const ArrayRef<std::vector<UTF16>> getStringTable() const { 158 return StringTable; 159 } 160 161 class TreeNode { 162 public: 163 template <typename T> 164 using Children = std::map<T, std::unique_ptr<TreeNode>>; 165 166 void print(ScopedPrinter &Writer, StringRef Name) const; 167 uint32_t getTreeSize() const; 168 uint32_t getStringIndex() const { return StringIndex; } 169 uint32_t getDataIndex() const { return DataIndex; } 170 uint16_t getMajorVersion() const { return MajorVersion; } 171 uint16_t getMinorVersion() const { return MinorVersion; } 172 uint32_t getCharacteristics() const { return Characteristics; } 173 bool checkIsDataNode() const { return IsDataNode; } 174 const Children<uint32_t> &getIDChildren() const { return IDChildren; } 175 const Children<std::string> &getStringChildren() const { 176 return StringChildren; 177 } 178 179 private: 180 friend class WindowsResourceParser; 181 182 static uint32_t StringCount; 183 static uint32_t DataCount; 184 185 static std::unique_ptr<TreeNode> createStringNode(); 186 static std::unique_ptr<TreeNode> createIDNode(); 187 static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, 188 uint16_t MinorVersion, 189 uint32_t Characteristics); 190 191 explicit TreeNode(bool IsStringNode); 192 TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, 193 uint32_t Characteristics); 194 195 void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString, 196 bool &IsNewNameString); 197 TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString); 198 TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString); 199 TreeNode &addLanguageNode(const ResourceEntryRef &Entry); 200 TreeNode &addChild(uint32_t ID, bool IsDataNode = false, 201 uint16_t MajorVersion = 0, uint16_t MinorVersion = 0, 202 uint32_t Characteristics = 0); 203 TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString); 204 205 bool IsDataNode = false; 206 uint32_t StringIndex; 207 uint32_t DataIndex; 208 Children<uint32_t> IDChildren; 209 Children<std::string> StringChildren; 210 uint16_t MajorVersion = 0; 211 uint16_t MinorVersion = 0; 212 uint32_t Characteristics = 0; 213 }; 214 215private: 216 TreeNode Root; 217 std::vector<std::vector<uint8_t>> Data; 218 std::vector<std::vector<UTF16>> StringTable; 219}; 220 221Expected<std::unique_ptr<MemoryBuffer>> 222writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, 223 const WindowsResourceParser &Parser); 224 225} // namespace object 226} // namespace llvm 227 228#endif 229