Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:20

0001 //===-- WindowsResource.h ---------------------------------------*- C++-*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===---------------------------------------------------------------------===//
0008 //
0009 // This file declares the .res file class.  .res files are intermediate
0010 // products of the typical resource-compilation process on Windows.  This
0011 // process is as follows:
0012 //
0013 // .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file
0014 //
0015 // .rc files are human-readable scripts that list all resources a program uses.
0016 //
0017 // They are compiled into .res files, which are a list of the resources in
0018 // binary form.
0019 //
0020 // Finally the data stored in the .res is compiled into a COFF file, where it
0021 // is organized in a directory tree structure for optimized access by the
0022 // program during runtime.
0023 //
0024 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx
0025 //
0026 //===---------------------------------------------------------------------===//
0027 
0028 #ifndef LLVM_OBJECT_WINDOWSRESOURCE_H
0029 #define LLVM_OBJECT_WINDOWSRESOURCE_H
0030 
0031 #include "llvm/ADT/ArrayRef.h"
0032 #include "llvm/BinaryFormat/COFF.h"
0033 #include "llvm/Object/Binary.h"
0034 #include "llvm/Object/Error.h"
0035 #include "llvm/Support/BinaryByteStream.h"
0036 #include "llvm/Support/BinaryStreamReader.h"
0037 #include "llvm/Support/ConvertUTF.h"
0038 #include "llvm/Support/Endian.h"
0039 #include "llvm/Support/Error.h"
0040 
0041 #include <map>
0042 
0043 namespace llvm {
0044 
0045 class raw_ostream;
0046 class ScopedPrinter;
0047 
0048 namespace object {
0049 
0050 class WindowsResource;
0051 class ResourceSectionRef;
0052 struct coff_resource_dir_table;
0053 
0054 const size_t WIN_RES_MAGIC_SIZE = 16;
0055 const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
0056 const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
0057 const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
0058 const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
0059 
0060 struct WinResHeaderPrefix {
0061   support::ulittle32_t DataSize;
0062   support::ulittle32_t HeaderSize;
0063 };
0064 
0065 // Type and Name may each either be an integer ID or a string.  This struct is
0066 // only used in the case where they are both IDs.
0067 struct WinResIDs {
0068   uint16_t TypeFlag;
0069   support::ulittle16_t TypeID;
0070   uint16_t NameFlag;
0071   support::ulittle16_t NameID;
0072 
0073   void setType(uint16_t ID) {
0074     TypeFlag = 0xffff;
0075     TypeID = ID;
0076   }
0077 
0078   void setName(uint16_t ID) {
0079     NameFlag = 0xffff;
0080     NameID = ID;
0081   }
0082 };
0083 
0084 struct WinResHeaderSuffix {
0085   support::ulittle32_t DataVersion;
0086   support::ulittle16_t MemoryFlags;
0087   support::ulittle16_t Language;
0088   support::ulittle32_t Version;
0089   support::ulittle32_t Characteristics;
0090 };
0091 
0092 class EmptyResError : public GenericBinaryError {
0093 public:
0094   EmptyResError(Twine Msg, object_error ECOverride)
0095       : GenericBinaryError(Msg, ECOverride) {}
0096 };
0097 
0098 class ResourceEntryRef {
0099 public:
0100   Error moveNext(bool &End);
0101   bool checkTypeString() const { return IsStringType; }
0102   ArrayRef<UTF16> getTypeString() const { return Type; }
0103   uint16_t getTypeID() const { return TypeID; }
0104   bool checkNameString() const { return IsStringName; }
0105   ArrayRef<UTF16> getNameString() const { return Name; }
0106   uint16_t getNameID() const { return NameID; }
0107   uint16_t getDataVersion() const { return Suffix->DataVersion; }
0108   uint16_t getLanguage() const { return Suffix->Language; }
0109   uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
0110   uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
0111   uint16_t getMinorVersion() const { return Suffix->Version; }
0112   uint32_t getCharacteristics() const { return Suffix->Characteristics; }
0113   ArrayRef<uint8_t> getData() const { return Data; }
0114 
0115 private:
0116   friend class WindowsResource;
0117 
0118   ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner);
0119   Error loadNext();
0120 
0121   static Expected<ResourceEntryRef> create(BinaryStreamRef Ref,
0122                                            const WindowsResource *Owner);
0123 
0124   BinaryStreamReader Reader;
0125   const WindowsResource *Owner;
0126   bool IsStringType;
0127   ArrayRef<UTF16> Type;
0128   uint16_t TypeID;
0129   bool IsStringName;
0130   ArrayRef<UTF16> Name;
0131   uint16_t NameID;
0132   const WinResHeaderSuffix *Suffix = nullptr;
0133   ArrayRef<uint8_t> Data;
0134 };
0135 
0136 class WindowsResource : public Binary {
0137 public:
0138   Expected<ResourceEntryRef> getHeadEntry();
0139 
0140   static bool classof(const Binary *V) { return V->isWinRes(); }
0141 
0142   static Expected<std::unique_ptr<WindowsResource>>
0143   createWindowsResource(MemoryBufferRef Source);
0144 
0145 private:
0146   friend class ResourceEntryRef;
0147 
0148   WindowsResource(MemoryBufferRef Source);
0149 
0150   BinaryByteStream BBS;
0151 };
0152 
0153 class WindowsResourceParser {
0154 public:
0155   class TreeNode;
0156   WindowsResourceParser(bool MinGW = false);
0157   Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
0158   Error parse(ResourceSectionRef &RSR, StringRef Filename,
0159               std::vector<std::string> &Duplicates);
0160   void cleanUpManifests(std::vector<std::string> &Duplicates);
0161   void printTree(raw_ostream &OS) const;
0162   const TreeNode &getTree() const { return Root; }
0163   ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
0164   ArrayRef<std::vector<UTF16>> getStringTable() const { return StringTable; }
0165 
0166   class TreeNode {
0167   public:
0168     template <typename T>
0169     using Children = std::map<T, std::unique_ptr<TreeNode>>;
0170 
0171     void print(ScopedPrinter &Writer, StringRef Name) const;
0172     uint32_t getTreeSize() const;
0173     uint32_t getStringIndex() const { return StringIndex; }
0174     uint32_t getDataIndex() const { return DataIndex; }
0175     uint16_t getMajorVersion() const { return MajorVersion; }
0176     uint16_t getMinorVersion() const { return MinorVersion; }
0177     uint32_t getCharacteristics() const { return Characteristics; }
0178     bool checkIsDataNode() const { return IsDataNode; }
0179     const Children<uint32_t> &getIDChildren() const { return IDChildren; }
0180     const Children<std::string> &getStringChildren() const {
0181       return StringChildren;
0182     }
0183 
0184   private:
0185     friend class WindowsResourceParser;
0186 
0187     // Index is the StringTable vector index for this node's name.
0188     static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
0189     static std::unique_ptr<TreeNode> createIDNode();
0190     // DataIndex is the Data vector index that the data node points at.
0191     static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
0192                                                     uint16_t MinorVersion,
0193                                                     uint32_t Characteristics,
0194                                                     uint32_t Origin,
0195                                                     uint32_t DataIndex);
0196 
0197     explicit TreeNode(uint32_t StringIndex);
0198     TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
0199              uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
0200 
0201     bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
0202                   std::vector<std::vector<uint8_t>> &Data,
0203                   std::vector<std::vector<UTF16>> &StringTable,
0204                   TreeNode *&Result);
0205     TreeNode &addTypeNode(const ResourceEntryRef &Entry,
0206                           std::vector<std::vector<UTF16>> &StringTable);
0207     TreeNode &addNameNode(const ResourceEntryRef &Entry,
0208                           std::vector<std::vector<UTF16>> &StringTable);
0209     bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
0210                          std::vector<std::vector<uint8_t>> &Data,
0211                          TreeNode *&Result);
0212     bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
0213                       uint32_t Characteristics, uint32_t Origin,
0214                       uint32_t DataIndex, TreeNode *&Result);
0215     TreeNode &addIDChild(uint32_t ID);
0216     TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
0217                            std::vector<std::vector<UTF16>> &StringTable);
0218     void shiftDataIndexDown(uint32_t Index);
0219 
0220     bool IsDataNode = false;
0221     uint32_t StringIndex;
0222     uint32_t DataIndex;
0223     Children<uint32_t> IDChildren;
0224     Children<std::string> StringChildren;
0225     uint16_t MajorVersion = 0;
0226     uint16_t MinorVersion = 0;
0227     uint32_t Characteristics = 0;
0228 
0229     // The .res file that defined this TreeNode, for diagnostics.
0230     // Index into InputFilenames.
0231     uint32_t Origin;
0232   };
0233 
0234   struct StringOrID {
0235     bool IsString;
0236     ArrayRef<UTF16> String;
0237     uint32_t ID = ~0u;
0238 
0239     StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
0240     StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
0241   };
0242 
0243 private:
0244   Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
0245                     const coff_resource_dir_table &Table, uint32_t Origin,
0246                     std::vector<StringOrID> &Context,
0247                     std::vector<std::string> &Duplicates);
0248   bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
0249   bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
0250 
0251   TreeNode Root;
0252   std::vector<std::vector<uint8_t>> Data;
0253   std::vector<std::vector<UTF16>> StringTable;
0254 
0255   std::vector<std::string> InputFilenames;
0256 
0257   bool MinGW;
0258 };
0259 
0260 Expected<std::unique_ptr<MemoryBuffer>>
0261 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
0262                          const WindowsResourceParser &Parser,
0263                          uint32_t TimeDateStamp);
0264 
0265 void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
0266 } // namespace object
0267 } // namespace llvm
0268 
0269 #endif