1 #pragma once
2 
3 #include "pe_constants.h"
4 #include "pe_header.h"
5 #include "pe_utils.h"
6 
7 #define RESOURCE_PTR(t, resdir, offset) reinterpret_cast<t*>(reinterpret_cast<size_t>(resdir) + offset)
8 
9 namespace REDasm {
10 
11 class PEResources
12 {
13     public:
14         enum: u32 { CURSORS = 1, BITMAPS = 2, ICONS = 3, MENUS = 4, DIALOGS = 5,
15                     STRING_TABLES = 6, FONT_DIRECTORY = 7, FONTS = 8, ACCELERATORS = 9,
16                     RCDATA = 10, MESSAGE_TABLES = 11, CURSOR_GROUPS = 12, ICON_GROUPS = 14,
17                     VERSION_INFO = 16, HTML_PAGES = 23, CONFIGURATION_FILES = 24 };
18 
19         typedef std::pair<ImageResourceDirectory*, ImageResourceDirectoryEntry*> ResourceItem;
20         typedef std::function<offset_location(address_t)> RvaToOffsetCallback;
21 
22     public:
23         PEResources(ImageResourceDirectory* resourcedirectory);
24         ResourceItem find(u16 id) const;
25         ResourceItem find(const std::string& name) const;
26         ResourceItem find(u16 id, const ResourceItem& parentres) const;
27         ResourceItem find(const std::string& name, const ResourceItem& parentres) const;
28 
29     public:
30         template<typename T1, typename T2> T1* data(const PEResources::ResourceItem &item, T2 loaderbase, const ImageNtHeaders* ntheaders, u64* size = nullptr) const;
31 
32     private:
33         ResourceItem find(u16 id, ImageResourceDirectory* resourcedir) const;
34         ResourceItem find(const std::string& name, ImageResourceDirectory* resourcedir) const;
35         std::string entryName(ImageResourceDirectoryEntry* entry) const;
36         std::string resourceid(u16 id) const;
37 
38     private:
39         std::map<u16, std::string> m_resourcenames;
40         ImageResourceDirectory* m_resourcedirectory;
41 };
42 
data(const PEResources::ResourceItem & item,T2 loaderbase,const ImageNtHeaders * ntheaders,u64 * size)43 template<typename T1, typename T2> T1* PEResources::data(const PEResources::ResourceItem &item, T2 loaderbase, const ImageNtHeaders* ntheaders, u64* size) const
44 {
45     if(!item.second->DataIsDirectory)
46     {
47         if(!item.second->OffsetToData)
48             return nullptr;
49 
50         ImageResourceDataEntry* dataentry = RESOURCE_PTR(ImageResourceDataEntry, m_resourcedirectory, item.second->OffsetToData);
51 
52         if(size)
53             *size = dataentry->Size;
54 
55         offset_location offset = PEUtils::rvaToOffset(ntheaders, dataentry->OffsetToData);
56 
57         if(!offset.valid)
58             return nullptr;
59 
60         return reinterpret_cast<T1*>(reinterpret_cast<size_t>(loaderbase) + offset);
61     }
62 
63     ImageResourceDirectory* resourcedir = RESOURCE_PTR(ImageResourceDirectory, m_resourcedirectory, item.second->OffsetToDirectory);
64     size_t c = resourcedir->NumberOfIdEntries + resourcedir->NumberOfNamedEntries;
65 
66     if(c != 1)
67         return nullptr;
68 
69     ImageResourceDirectoryEntry* entry = reinterpret_cast<ImageResourceDirectoryEntry*>(resourcedir + 1);
70     return this->data<T1, T2>(std::make_pair(resourcedir, entry), loaderbase, ntheaders, size);
71 }
72 
73 } // namespace REDasm
74