WindowsResource.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //===-- WindowsResource.h ---------------------------------------*- C++-*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===---------------------------------------------------------------------===//
  8. //
  9. // This file declares the .res file class. .res files are intermediate
  10. // products of the typical resource-compilation process on Windows. This
  11. // process is as follows:
  12. //
  13. // .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file
  14. //
  15. // .rc files are human-readable scripts that list all resources a program uses.
  16. //
  17. // They are compiled into .res files, which are a list of the resources in
  18. // binary form.
  19. //
  20. // Finally the data stored in the .res is compiled into a COFF file, where it
  21. // is organized in a directory tree structure for optimized access by the
  22. // program during runtime.
  23. //
  24. // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx
  25. //
  26. //===---------------------------------------------------------------------===//
  27. #ifndef LLVM_OBJECT_WINDOWSRESOURCE_H
  28. #define LLVM_OBJECT_WINDOWSRESOURCE_H
  29. #include "llvm/ADT/ArrayRef.h"
  30. #include "llvm/BinaryFormat/COFF.h"
  31. #include "llvm/Object/Binary.h"
  32. #include "llvm/Object/COFF.h"
  33. #include "llvm/Object/Error.h"
  34. #include "llvm/Support/BinaryByteStream.h"
  35. #include "llvm/Support/BinaryStreamReader.h"
  36. #include "llvm/Support/ConvertUTF.h"
  37. #include "llvm/Support/Endian.h"
  38. #include "llvm/Support/Error.h"
  39. #include <map>
  40. namespace llvm {
  41. class raw_ostream;
  42. class ScopedPrinter;
  43. namespace object {
  44. class WindowsResource;
  45. class ResourceSectionRef;
  46. const size_t WIN_RES_MAGIC_SIZE = 16;
  47. const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
  48. const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
  49. const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
  50. const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
  51. struct WinResHeaderPrefix {
  52. support::ulittle32_t DataSize;
  53. support::ulittle32_t HeaderSize;
  54. };
  55. // Type and Name may each either be an integer ID or a string. This struct is
  56. // only used in the case where they are both IDs.
  57. struct WinResIDs {
  58. uint16_t TypeFlag;
  59. support::ulittle16_t TypeID;
  60. uint16_t NameFlag;
  61. support::ulittle16_t NameID;
  62. void setType(uint16_t ID) {
  63. TypeFlag = 0xffff;
  64. TypeID = ID;
  65. }
  66. void setName(uint16_t ID) {
  67. NameFlag = 0xffff;
  68. NameID = ID;
  69. }
  70. };
  71. struct WinResHeaderSuffix {
  72. support::ulittle32_t DataVersion;
  73. support::ulittle16_t MemoryFlags;
  74. support::ulittle16_t Language;
  75. support::ulittle32_t Version;
  76. support::ulittle32_t Characteristics;
  77. };
  78. class EmptyResError : public GenericBinaryError {
  79. public:
  80. EmptyResError(Twine Msg, object_error ECOverride)
  81. : GenericBinaryError(Msg, ECOverride) {}
  82. };
  83. class ResourceEntryRef {
  84. public:
  85. Error moveNext(bool &End);
  86. bool checkTypeString() const { return IsStringType; }
  87. ArrayRef<UTF16> getTypeString() const { return Type; }
  88. uint16_t getTypeID() const { return TypeID; }
  89. bool checkNameString() const { return IsStringName; }
  90. ArrayRef<UTF16> getNameString() const { return Name; }
  91. uint16_t getNameID() const { return NameID; }
  92. uint16_t getDataVersion() const { return Suffix->DataVersion; }
  93. uint16_t getLanguage() const { return Suffix->Language; }
  94. uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
  95. uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
  96. uint16_t getMinorVersion() const { return Suffix->Version; }
  97. uint32_t getCharacteristics() const { return Suffix->Characteristics; }
  98. ArrayRef<uint8_t> getData() const { return Data; }
  99. private:
  100. friend class WindowsResource;
  101. ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner);
  102. Error loadNext();
  103. static Expected<ResourceEntryRef> create(BinaryStreamRef Ref,
  104. const WindowsResource *Owner);
  105. BinaryStreamReader Reader;
  106. const WindowsResource *Owner;
  107. bool IsStringType;
  108. ArrayRef<UTF16> Type;
  109. uint16_t TypeID;
  110. bool IsStringName;
  111. ArrayRef<UTF16> Name;
  112. uint16_t NameID;
  113. const WinResHeaderSuffix *Suffix = nullptr;
  114. ArrayRef<uint8_t> Data;
  115. };
  116. class WindowsResource : public Binary {
  117. public:
  118. Expected<ResourceEntryRef> getHeadEntry();
  119. static bool classof(const Binary *V) { return V->isWinRes(); }
  120. static Expected<std::unique_ptr<WindowsResource>>
  121. createWindowsResource(MemoryBufferRef Source);
  122. private:
  123. friend class ResourceEntryRef;
  124. WindowsResource(MemoryBufferRef Source);
  125. BinaryByteStream BBS;
  126. };
  127. class WindowsResourceParser {
  128. public:
  129. class TreeNode;
  130. WindowsResourceParser(bool MinGW = false);
  131. Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
  132. Error parse(ResourceSectionRef &RSR, StringRef Filename,
  133. std::vector<std::string> &Duplicates);
  134. void cleanUpManifests(std::vector<std::string> &Duplicates);
  135. void printTree(raw_ostream &OS) const;
  136. const TreeNode &getTree() const { return Root; }
  137. ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
  138. ArrayRef<std::vector<UTF16>> getStringTable() const { return StringTable; }
  139. class TreeNode {
  140. public:
  141. template <typename T>
  142. using Children = std::map<T, std::unique_ptr<TreeNode>>;
  143. void print(ScopedPrinter &Writer, StringRef Name) const;
  144. uint32_t getTreeSize() const;
  145. uint32_t getStringIndex() const { return StringIndex; }
  146. uint32_t getDataIndex() const { return DataIndex; }
  147. uint16_t getMajorVersion() const { return MajorVersion; }
  148. uint16_t getMinorVersion() const { return MinorVersion; }
  149. uint32_t getCharacteristics() const { return Characteristics; }
  150. bool checkIsDataNode() const { return IsDataNode; }
  151. const Children<uint32_t> &getIDChildren() const { return IDChildren; }
  152. const Children<std::string> &getStringChildren() const {
  153. return StringChildren;
  154. }
  155. private:
  156. friend class WindowsResourceParser;
  157. // Index is the StringTable vector index for this node's name.
  158. static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
  159. static std::unique_ptr<TreeNode> createIDNode();
  160. // DataIndex is the Data vector index that the data node points at.
  161. static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
  162. uint16_t MinorVersion,
  163. uint32_t Characteristics,
  164. uint32_t Origin,
  165. uint32_t DataIndex);
  166. explicit TreeNode(uint32_t StringIndex);
  167. TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
  168. uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
  169. bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
  170. std::vector<std::vector<uint8_t>> &Data,
  171. std::vector<std::vector<UTF16>> &StringTable,
  172. TreeNode *&Result);
  173. TreeNode &addTypeNode(const ResourceEntryRef &Entry,
  174. std::vector<std::vector<UTF16>> &StringTable);
  175. TreeNode &addNameNode(const ResourceEntryRef &Entry,
  176. std::vector<std::vector<UTF16>> &StringTable);
  177. bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
  178. std::vector<std::vector<uint8_t>> &Data,
  179. TreeNode *&Result);
  180. bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
  181. uint32_t Characteristics, uint32_t Origin,
  182. uint32_t DataIndex, TreeNode *&Result);
  183. TreeNode &addIDChild(uint32_t ID);
  184. TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
  185. std::vector<std::vector<UTF16>> &StringTable);
  186. void shiftDataIndexDown(uint32_t Index);
  187. bool IsDataNode = false;
  188. uint32_t StringIndex;
  189. uint32_t DataIndex;
  190. Children<uint32_t> IDChildren;
  191. Children<std::string> StringChildren;
  192. uint16_t MajorVersion = 0;
  193. uint16_t MinorVersion = 0;
  194. uint32_t Characteristics = 0;
  195. // The .res file that defined this TreeNode, for diagnostics.
  196. // Index into InputFilenames.
  197. uint32_t Origin;
  198. };
  199. struct StringOrID {
  200. bool IsString;
  201. ArrayRef<UTF16> String;
  202. uint32_t ID;
  203. StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
  204. StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
  205. };
  206. private:
  207. Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
  208. const coff_resource_dir_table &Table, uint32_t Origin,
  209. std::vector<StringOrID> &Context,
  210. std::vector<std::string> &Duplicates);
  211. bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
  212. bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
  213. TreeNode Root;
  214. std::vector<std::vector<uint8_t>> Data;
  215. std::vector<std::vector<UTF16>> StringTable;
  216. std::vector<std::string> InputFilenames;
  217. bool MinGW;
  218. };
  219. Expected<std::unique_ptr<MemoryBuffer>>
  220. writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
  221. const WindowsResourceParser &Parser,
  222. uint32_t TimeDateStamp);
  223. void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
  224. } // namespace object
  225. } // namespace llvm
  226. #endif