WindowsResource.h 9.3 KB

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