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