-
Notifications
You must be signed in to change notification settings - Fork 0
/
interfaces.h
111 lines (88 loc) · 2.52 KB
/
interfaces.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once
class Interfaces {
private:
// used internally to register classes.
class InterfaceReg {
private:
using create_t = void* (__cdecl*)();
public:
create_t m_create_fn;
const char* m_name;
InterfaceReg* m_next;
};
struct interface_t {
std::string m_name;
Address m_ptr;
};
// holds every interface used by the game.
std::vector< interface_t > m_interfaces;
public:
// ctor.
__forceinline Interfaces() : m_interfaces{} {
PE::modules_t modules;
Address ci;
InterfaceReg* reg;
if (!PE::GetAllModules(modules))
return;
for (const auto& m : modules) {
// get CreateInterface export.
ci = PE::GetExport(m, HASH("CreateInterface"));
if (!Address::valid(ci))
continue;
// there is a jump to the real CreateInterface function.
if (ci.at< uint8_t >(0x4) == 0xe9) {
// displaced jump - take it
ci = ci.rel32(0x5);
// we are now in the true CreateInterface function.
// check for ESI register at 5th instruction
// ptr to linked list is after the MOV ESI instruction.
if (ci.at< uint8_t >(0x5) == 0x35) {
// get ptr to linked list.
reg = ci.add(0x6).get< InterfaceReg* >(2);
// iterate list.
CreateEntries(reg);
}
}
// check for ESI register at 2nd instruction
// ptr to linked list is after the MOV ESI instruction.
else if (ci.at< uint8_t >(0x2) == 0x35) {
// get ptr to linked list.
reg = ci.add(0x3).get< InterfaceReg* >(2);
// iterate list.
CreateEntries(reg);
}
}
}
__forceinline void CreateEntries(InterfaceReg* list) {
// iterate single linked list.
for (list; list != nullptr; list = list->m_next) {
// invalid name.
if (!list->m_name)
continue;
// add to vector.
m_interfaces.push_back({ list->m_name, (uintptr_t)list->m_create_fn() });
}
}
// get interface.
template< typename t = Address >
__declspec(noinline) t get(const hash32_t name, size_t skip = 0, bool truncate = true) {
std::string interface_name;
for (const auto& i : m_interfaces) {
// make a copy of the interface's name.
interface_name = i.m_name;
// truncate version number.
if (truncate)
interface_name.resize(interface_name.size() - 3);
// compare hash.
if (FNV1a::get(interface_name) == name) {
// skip this interface if a newer one is available.
if (skip > 0) {
--skip;
continue;
}
return i.m_ptr.as< t >();
}
}
return t{};
}
};