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/Error.h"
35 #include "llvm/Support/BinaryByteStream.h"
36 #include "llvm/Support/BinaryStreamReader.h"
37 #include "llvm/Support/ConvertUTF.h"
38 #include "llvm/Support/Endian.h"
39 #include "llvm/Support/Error.h"
40 #include "llvm/Support/ScopedPrinter.h"
47 class WindowsResource
;
49 const size_t WIN_RES_MAGIC_SIZE
= 16;
50 const size_t WIN_RES_NULL_ENTRY_SIZE
= 16;
51 const uint32_t WIN_RES_HEADER_ALIGNMENT
= 4;
52 const uint32_t WIN_RES_DATA_ALIGNMENT
= 4;
53 const uint16_t WIN_RES_PURE_MOVEABLE
= 0x0030;
55 struct WinResHeaderPrefix
{
56 support::ulittle32_t DataSize
;
57 support::ulittle32_t HeaderSize
;
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.
64 support::ulittle16_t TypeID
;
66 support::ulittle16_t NameID
;
68 void setType(uint16_t ID
) {
73 void setName(uint16_t ID
) {
79 struct WinResHeaderSuffix
{
80 support::ulittle32_t DataVersion
;
81 support::ulittle16_t MemoryFlags
;
82 support::ulittle16_t Language
;
83 support::ulittle32_t Version
;
84 support::ulittle32_t Characteristics
;
87 class EmptyResError
: public GenericBinaryError
{
89 EmptyResError(Twine Msg
, object_error ECOverride
)
90 : GenericBinaryError(Msg
, ECOverride
) {}
93 class ResourceEntryRef
{
95 Error
moveNext(bool &End
);
96 bool checkTypeString() const { return IsStringType
; }
97 ArrayRef
<UTF16
> getTypeString() const { return Type
; }
98 uint16_t getTypeID() const { return TypeID
; }
99 bool checkNameString() const { return IsStringName
; }
100 ArrayRef
<UTF16
> getNameString() const { return Name
; }
101 uint16_t getNameID() const { return NameID
; }
102 uint16_t getDataVersion() const { return Suffix
->DataVersion
; }
103 uint16_t getLanguage() const { return Suffix
->Language
; }
104 uint16_t getMemoryFlags() const { return Suffix
->MemoryFlags
; }
105 uint16_t getMajorVersion() const { return Suffix
->Version
>> 16; }
106 uint16_t getMinorVersion() const { return Suffix
->Version
; }
107 uint32_t getCharacteristics() const { return Suffix
->Characteristics
; }
108 ArrayRef
<uint8_t> getData() const { return Data
; }
111 friend class WindowsResource
;
113 ResourceEntryRef(BinaryStreamRef Ref
, const WindowsResource
*Owner
);
116 static Expected
<ResourceEntryRef
> create(BinaryStreamRef Ref
,
117 const WindowsResource
*Owner
);
119 BinaryStreamReader Reader
;
121 ArrayRef
<UTF16
> Type
;
124 ArrayRef
<UTF16
> Name
;
126 const WinResHeaderSuffix
*Suffix
= nullptr;
127 ArrayRef
<uint8_t> Data
;
130 class WindowsResource
: public Binary
{
132 Expected
<ResourceEntryRef
> getHeadEntry();
134 static bool classof(const Binary
*V
) { return V
->isWinRes(); }
136 static Expected
<std::unique_ptr
<WindowsResource
>>
137 createWindowsResource(MemoryBufferRef Source
);
140 friend class ResourceEntryRef
;
142 WindowsResource(MemoryBufferRef Source
);
144 BinaryByteStream BBS
;
147 class WindowsResourceParser
{
150 WindowsResourceParser();
151 Error
parse(WindowsResource
*WR
);
152 void printTree(raw_ostream
&OS
) const;
153 const TreeNode
&getTree() const { return Root
; }
154 const ArrayRef
<std::vector
<uint8_t>> getData() const { return Data
; }
155 const ArrayRef
<std::vector
<UTF16
>> getStringTable() const {
161 template <typename T
>
162 using Children
= std::map
<T
, std::unique_ptr
<TreeNode
>>;
164 void print(ScopedPrinter
&Writer
, StringRef Name
) const;
165 uint32_t getTreeSize() const;
166 uint32_t getStringIndex() const { return StringIndex
; }
167 uint32_t getDataIndex() const { return DataIndex
; }
168 uint16_t getMajorVersion() const { return MajorVersion
; }
169 uint16_t getMinorVersion() const { return MinorVersion
; }
170 uint32_t getCharacteristics() const { return Characteristics
; }
171 bool checkIsDataNode() const { return IsDataNode
; }
172 const Children
<uint32_t> &getIDChildren() const { return IDChildren
; }
173 const Children
<std::string
> &getStringChildren() const {
174 return StringChildren
;
178 friend class WindowsResourceParser
;
180 static uint32_t StringCount
;
181 static uint32_t DataCount
;
183 static std::unique_ptr
<TreeNode
> createStringNode();
184 static std::unique_ptr
<TreeNode
> createIDNode();
185 static std::unique_ptr
<TreeNode
> createDataNode(uint16_t MajorVersion
,
186 uint16_t MinorVersion
,
187 uint32_t Characteristics
);
189 explicit TreeNode(bool IsStringNode
);
190 TreeNode(uint16_t MajorVersion
, uint16_t MinorVersion
,
191 uint32_t Characteristics
);
193 void addEntry(const ResourceEntryRef
&Entry
, bool &IsNewTypeString
,
194 bool &IsNewNameString
);
195 TreeNode
&addTypeNode(const ResourceEntryRef
&Entry
, bool &IsNewTypeString
);
196 TreeNode
&addNameNode(const ResourceEntryRef
&Entry
, bool &IsNewNameString
);
197 TreeNode
&addLanguageNode(const ResourceEntryRef
&Entry
);
198 TreeNode
&addChild(uint32_t ID
, bool IsDataNode
= false,
199 uint16_t MajorVersion
= 0, uint16_t MinorVersion
= 0,
200 uint32_t Characteristics
= 0);
201 TreeNode
&addChild(ArrayRef
<UTF16
> NameRef
, bool &IsNewString
);
203 bool IsDataNode
= false;
204 uint32_t StringIndex
;
206 Children
<uint32_t> IDChildren
;
207 Children
<std::string
> StringChildren
;
208 uint16_t MajorVersion
= 0;
209 uint16_t MinorVersion
= 0;
210 uint32_t Characteristics
= 0;
215 std::vector
<std::vector
<uint8_t>> Data
;
216 std::vector
<std::vector
<UTF16
>> StringTable
;
219 Expected
<std::unique_ptr
<MemoryBuffer
>>
220 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType
,
221 const WindowsResourceParser
&Parser
);
223 } // namespace object