• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
45 namespace llvm {
46 namespace object {
47 
48 class WindowsResource;
49 
50 const size_t WIN_RES_MAGIC_SIZE = 16;
51 const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
52 const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
53 const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
54 const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
55 
56 struct 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.
63 struct WinResIDs {
64   uint16_t TypeFlag;
65   support::ulittle16_t TypeID;
66   uint16_t NameFlag;
67   support::ulittle16_t NameID;
68 
setTypeWinResIDs69   void setType(uint16_t ID) {
70     TypeFlag = 0xffff;
71     TypeID = ID;
72   }
73 
setNameWinResIDs74   void setName(uint16_t ID) {
75     NameFlag = 0xffff;
76     NameID = ID;
77   }
78 };
79 
80 struct 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 
88 class EmptyResError : public GenericBinaryError {
89 public:
EmptyResError(Twine Msg,object_error ECOverride)90   EmptyResError(Twine Msg, object_error ECOverride)
91       : GenericBinaryError(Msg, ECOverride) {}
92 };
93 
94 class ResourceEntryRef {
95 public:
96   Error moveNext(bool &End);
checkTypeString()97   bool checkTypeString() const { return IsStringType; }
getTypeString()98   ArrayRef<UTF16> getTypeString() const { return Type; }
getTypeID()99   uint16_t getTypeID() const { return TypeID; }
checkNameString()100   bool checkNameString() const { return IsStringName; }
getNameString()101   ArrayRef<UTF16> getNameString() const { return Name; }
getNameID()102   uint16_t getNameID() const { return NameID; }
getDataVersion()103   uint16_t getDataVersion() const { return Suffix->DataVersion; }
getLanguage()104   uint16_t getLanguage() const { return Suffix->Language; }
getMemoryFlags()105   uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
getMajorVersion()106   uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
getMinorVersion()107   uint16_t getMinorVersion() const { return Suffix->Version; }
getCharacteristics()108   uint32_t getCharacteristics() const { return Suffix->Characteristics; }
getData()109   ArrayRef<uint8_t> getData() const { return Data; }
110 
111 private:
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 };
130 
131 class WindowsResource : public Binary {
132 public:
133   Expected<ResourceEntryRef> getHeadEntry();
134 
classof(const Binary * V)135   static bool classof(const Binary *V) { return V->isWinRes(); }
136 
137   static Expected<std::unique_ptr<WindowsResource>>
138   createWindowsResource(MemoryBufferRef Source);
139 
140 private:
141   friend class ResourceEntryRef;
142 
143   WindowsResource(MemoryBufferRef Source);
144 
145   BinaryByteStream BBS;
146 };
147 
148 class WindowsResourceParser {
149 public:
150   class TreeNode;
151   WindowsResourceParser();
152   Error parse(WindowsResource *WR);
153   void printTree(raw_ostream &OS) const;
getTree()154   const TreeNode &getTree() const { return Root; }
getData()155   const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
getStringTable()156   const ArrayRef<std::vector<UTF16>> getStringTable() const {
157     return StringTable;
158   }
159 
160   class TreeNode {
161   public:
162     template <typename T>
163     using Children = std::map<T, std::unique_ptr<TreeNode>>;
164 
165     void print(ScopedPrinter &Writer, StringRef Name) const;
166     uint32_t getTreeSize() const;
getStringIndex()167     uint32_t getStringIndex() const { return StringIndex; }
getDataIndex()168     uint32_t getDataIndex() const { return DataIndex; }
getMajorVersion()169     uint16_t getMajorVersion() const { return MajorVersion; }
getMinorVersion()170     uint16_t getMinorVersion() const { return MinorVersion; }
getCharacteristics()171     uint32_t getCharacteristics() const { return Characteristics; }
checkIsDataNode()172     bool checkIsDataNode() const { return IsDataNode; }
getIDChildren()173     const Children<uint32_t> &getIDChildren() const { return IDChildren; }
getStringChildren()174     const Children<std::string> &getStringChildren() const {
175       return StringChildren;
176     }
177 
178   private:
179     friend class WindowsResourceParser;
180 
181     static uint32_t StringCount;
182     static uint32_t DataCount;
183 
184     static std::unique_ptr<TreeNode> createStringNode();
185     static std::unique_ptr<TreeNode> createIDNode();
186     static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
187                                                     uint16_t MinorVersion,
188                                                     uint32_t Characteristics);
189 
190     explicit TreeNode(bool IsStringNode);
191     TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
192              uint32_t Characteristics);
193 
194     void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString,
195                   bool &IsNewNameString);
196     TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
197     TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
198     TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
199     TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
200                        uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
201                        uint32_t Characteristics = 0);
202     TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
203 
204     bool IsDataNode = false;
205     uint32_t StringIndex;
206     uint32_t DataIndex;
207     Children<uint32_t> IDChildren;
208     Children<std::string> StringChildren;
209     uint16_t MajorVersion = 0;
210     uint16_t MinorVersion = 0;
211     uint32_t Characteristics = 0;
212   };
213 
214 private:
215   TreeNode Root;
216   std::vector<std::vector<uint8_t>> Data;
217   std::vector<std::vector<UTF16>> StringTable;
218 };
219 
220 Expected<std::unique_ptr<MemoryBuffer>>
221 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
222                          const WindowsResourceParser &Parser);
223 
224 } // namespace object
225 } // namespace llvm
226 
227 #endif
228