1 //===-- WindowsResource.h ---------------------------------------*- C++-*-===//
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
7 //===---------------------------------------------------------------------===//
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:
13 // .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file
15 // .rc files are human-readable scripts that list all resources a program uses.
17 // They are compiled into .res files, which are a list of the resources in
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.
24 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx
26 //===---------------------------------------------------------------------===//
28 #ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
29 #define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
31 #include "llvm/ADT/ArrayRef.h"
32 #include "llvm/BinaryFormat/COFF.h"
33 #include "llvm/Object/Binary.h"
34 #include "llvm/Object/COFF.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"
51 class WindowsResource
;
52 class ResourceSectionRef
;
54 const size_t WIN_RES_MAGIC_SIZE
= 16;
55 const size_t WIN_RES_NULL_ENTRY_SIZE
= 16;
56 const uint32_t WIN_RES_HEADER_ALIGNMENT
= 4;
57 const uint32_t WIN_RES_DATA_ALIGNMENT
= 4;
58 const uint16_t WIN_RES_PURE_MOVEABLE
= 0x0030;
60 struct WinResHeaderPrefix
{
61 support::ulittle32_t DataSize
;
62 support::ulittle32_t HeaderSize
;
65 // Type and Name may each either be an integer ID or a string. This struct is
66 // only used in the case where they are both IDs.
69 support::ulittle16_t TypeID
;
71 support::ulittle16_t NameID
;
73 void setType(uint16_t ID
) {
78 void setName(uint16_t ID
) {
84 struct WinResHeaderSuffix
{
85 support::ulittle32_t DataVersion
;
86 support::ulittle16_t MemoryFlags
;
87 support::ulittle16_t Language
;
88 support::ulittle32_t Version
;
89 support::ulittle32_t Characteristics
;
92 class EmptyResError
: public GenericBinaryError
{
94 EmptyResError(Twine Msg
, object_error ECOverride
)
95 : GenericBinaryError(Msg
, ECOverride
) {}
98 class ResourceEntryRef
{
100 Error
moveNext(bool &End
);
101 bool checkTypeString() const { return IsStringType
; }
102 ArrayRef
<UTF16
> getTypeString() const { return Type
; }
103 uint16_t getTypeID() const { return TypeID
; }
104 bool checkNameString() const { return IsStringName
; }
105 ArrayRef
<UTF16
> getNameString() const { return Name
; }
106 uint16_t getNameID() const { return NameID
; }
107 uint16_t getDataVersion() const { return Suffix
->DataVersion
; }
108 uint16_t getLanguage() const { return Suffix
->Language
; }
109 uint16_t getMemoryFlags() const { return Suffix
->MemoryFlags
; }
110 uint16_t getMajorVersion() const { return Suffix
->Version
>> 16; }
111 uint16_t getMinorVersion() const { return Suffix
->Version
; }
112 uint32_t getCharacteristics() const { return Suffix
->Characteristics
; }
113 ArrayRef
<uint8_t> getData() const { return Data
; }
116 friend class WindowsResource
;
118 ResourceEntryRef(BinaryStreamRef Ref
, const WindowsResource
*Owner
);
121 static Expected
<ResourceEntryRef
> create(BinaryStreamRef Ref
,
122 const WindowsResource
*Owner
);
124 BinaryStreamReader Reader
;
125 const WindowsResource
*Owner
;
127 ArrayRef
<UTF16
> Type
;
130 ArrayRef
<UTF16
> Name
;
132 const WinResHeaderSuffix
*Suffix
= nullptr;
133 ArrayRef
<uint8_t> Data
;
136 class WindowsResource
: public Binary
{
138 Expected
<ResourceEntryRef
> getHeadEntry();
140 static bool classof(const Binary
*V
) { return V
->isWinRes(); }
142 static Expected
<std::unique_ptr
<WindowsResource
>>
143 createWindowsResource(MemoryBufferRef Source
);
146 friend class ResourceEntryRef
;
148 WindowsResource(MemoryBufferRef Source
);
150 BinaryByteStream BBS
;
153 class WindowsResourceParser
{
156 WindowsResourceParser(bool MinGW
= false);
157 Error
parse(WindowsResource
*WR
, std::vector
<std::string
> &Duplicates
);
158 Error
parse(ResourceSectionRef
&RSR
, StringRef Filename
,
159 std::vector
<std::string
> &Duplicates
);
160 void cleanUpManifests(std::vector
<std::string
> &Duplicates
);
161 void printTree(raw_ostream
&OS
) const;
162 const TreeNode
&getTree() const { return Root
; }
163 const ArrayRef
<std::vector
<uint8_t>> getData() const { return Data
; }
164 const ArrayRef
<std::vector
<UTF16
>> getStringTable() const {
170 template <typename T
>
171 using Children
= std::map
<T
, std::unique_ptr
<TreeNode
>>;
173 void print(ScopedPrinter
&Writer
, StringRef Name
) const;
174 uint32_t getTreeSize() const;
175 uint32_t getStringIndex() const { return StringIndex
; }
176 uint32_t getDataIndex() const { return DataIndex
; }
177 uint16_t getMajorVersion() const { return MajorVersion
; }
178 uint16_t getMinorVersion() const { return MinorVersion
; }
179 uint32_t getCharacteristics() const { return Characteristics
; }
180 bool checkIsDataNode() const { return IsDataNode
; }
181 const Children
<uint32_t> &getIDChildren() const { return IDChildren
; }
182 const Children
<std::string
> &getStringChildren() const {
183 return StringChildren
;
187 friend class WindowsResourceParser
;
189 // Index is the StringTable vector index for this node's name.
190 static std::unique_ptr
<TreeNode
> createStringNode(uint32_t Index
);
191 static std::unique_ptr
<TreeNode
> createIDNode();
192 // DataIndex is the Data vector index that the data node points at.
193 static std::unique_ptr
<TreeNode
> createDataNode(uint16_t MajorVersion
,
194 uint16_t MinorVersion
,
195 uint32_t Characteristics
,
199 explicit TreeNode(uint32_t StringIndex
);
200 TreeNode(uint16_t MajorVersion
, uint16_t MinorVersion
,
201 uint32_t Characteristics
, uint32_t Origin
, uint32_t DataIndex
);
203 bool addEntry(const ResourceEntryRef
&Entry
, uint32_t Origin
,
204 std::vector
<std::vector
<uint8_t>> &Data
,
205 std::vector
<std::vector
<UTF16
>> &StringTable
,
207 TreeNode
&addTypeNode(const ResourceEntryRef
&Entry
,
208 std::vector
<std::vector
<UTF16
>> &StringTable
);
209 TreeNode
&addNameNode(const ResourceEntryRef
&Entry
,
210 std::vector
<std::vector
<UTF16
>> &StringTable
);
211 bool addLanguageNode(const ResourceEntryRef
&Entry
, uint32_t Origin
,
212 std::vector
<std::vector
<uint8_t>> &Data
,
214 bool addDataChild(uint32_t ID
, uint16_t MajorVersion
, uint16_t MinorVersion
,
215 uint32_t Characteristics
, uint32_t Origin
,
216 uint32_t DataIndex
, TreeNode
*&Result
);
217 TreeNode
&addIDChild(uint32_t ID
);
218 TreeNode
&addNameChild(ArrayRef
<UTF16
> NameRef
,
219 std::vector
<std::vector
<UTF16
>> &StringTable
);
220 void shiftDataIndexDown(uint32_t Index
);
222 bool IsDataNode
= false;
223 uint32_t StringIndex
;
225 Children
<uint32_t> IDChildren
;
226 Children
<std::string
> StringChildren
;
227 uint16_t MajorVersion
= 0;
228 uint16_t MinorVersion
= 0;
229 uint32_t Characteristics
= 0;
231 // The .res file that defined this TreeNode, for diagnostics.
232 // Index into InputFilenames.
238 ArrayRef
<UTF16
> String
;
241 StringOrID(uint32_t ID
) : IsString(false), ID(ID
) {}
242 StringOrID(ArrayRef
<UTF16
> String
) : IsString(true), String(String
) {}
246 Error
addChildren(TreeNode
&Node
, ResourceSectionRef
&RSR
,
247 const coff_resource_dir_table
&Table
, uint32_t Origin
,
248 std::vector
<StringOrID
> &Context
,
249 std::vector
<std::string
> &Duplicates
);
250 bool shouldIgnoreDuplicate(const ResourceEntryRef
&Entry
) const;
251 bool shouldIgnoreDuplicate(const std::vector
<StringOrID
> &Context
) const;
254 std::vector
<std::vector
<uint8_t>> Data
;
255 std::vector
<std::vector
<UTF16
>> StringTable
;
257 std::vector
<std::string
> InputFilenames
;
262 Expected
<std::unique_ptr
<MemoryBuffer
>>
263 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType
,
264 const WindowsResourceParser
&Parser
,
265 uint32_t TimeDateStamp
);
267 void printResourceTypeName(uint16_t TypeID
, raw_ostream
&OS
);
268 } // namespace object