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