/
MemAccess.h
212 lines (181 loc) · 6.41 KB
/
MemAccess.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/**
* SA2 Mod Loader.
* Memory access inline functions.
*/
#ifndef MODLOADER_MEMACCESS_H
#define MODLOADER_MEMACCESS_H
#include <stdint.h>
// Utility Functions
#ifdef __cplusplus
// C++ version.
/**
* Get the number of elements in an array.
* @return Number of elements in the array.
*/
template <typename Tret = size_t, typename T, size_t N>
static inline Tret LengthOfArray(const T(&)[N])
{
return (Tret)N;
}
/**
* Get the size of an array.
* @return Size of the array, in bytes.
*/
template <typename Tret = size_t, typename T, size_t N>
static inline Tret SizeOfArray(const T(&)[N])
{
return (Tret)(N * sizeof(T));
}
// Macros for functions that need both an array
// and the array length or size.
#define arrayptrandlengthT(data,T) data, LengthOfArray<T>(data)
#define arraylengthandptrT(data,T) LengthOfArray<T>(data), data
#define arrayptrandsizeT(data,T) data, SizeOfArray<T>(data)
#define arraysizeandptrT(data,T) SizeOfArray<T>(data), data
#else
// C version.
/**
* Number of elements in an array.
*
* Includes a static check for pointers to make sure
* a dynamically-allocated array wasn't specified.
* Reference: http://stackoverflow.com/questions/8018843/macro-definition-array-size
*/
#define LengthOfArray(x) \
((int)(((sizeof(x) / sizeof(x[0]))) / \
(size_t)(!(sizeof(x) % sizeof(x[0])))))
#define SizeOfArray(x) sizeof(x)
#endif
// Macros for functions that need both an array
// and the array length or size.
#define arrayptrandlength(data) data, LengthOfArray(data)
#define arraylengthandptr(data) LengthOfArray(data), data
#define arrayptrandsize(data) data, SizeOfArray(data)
#define arraysizeandptr(data) SizeOfArray(data), data
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
static HANDLE curproc;
static bool curprocinitialized = false;
static inline BOOL WriteData(void *writeaddress, const void *data, SIZE_T datasize, SIZE_T *byteswritten)
{
if (!curprocinitialized)
{
curproc = GetCurrentProcess();
curprocinitialized = true;
}
return WriteProcessMemory(curproc, writeaddress, data, datasize, byteswritten);
}
static inline BOOL WriteData(void *writeaddress, const void *data, SIZE_T datasize)
{
return WriteData(writeaddress, data, datasize, nullptr);
}
template<typename T>
static inline BOOL WriteData(T const *writeaddress, const T data, SIZE_T *byteswritten)
{
return WriteData((void*)writeaddress, (void*)&data, (SIZE_T)sizeof(data), byteswritten);
}
template<typename T>
static inline BOOL WriteData(T const *writeaddress, const T data)
{
return WriteData(writeaddress, data, nullptr);
}
template<typename T>
static inline BOOL WriteData(T *writeaddress, const T &data, SIZE_T *byteswritten)
{
return WriteData(writeaddress, &data, sizeof(data), byteswritten);
}
template<typename T>
static inline BOOL WriteData(T *writeaddress, const T &data)
{
return WriteData(writeaddress, data, nullptr);
}
template <typename T, size_t N>
static inline BOOL WriteData(void *writeaddress, const T(&data)[N], SIZE_T *byteswritten)
{
return WriteData(writeaddress, data, SizeOfArray(data), byteswritten);
}
template <typename T, size_t N>
static inline BOOL WriteData(void *writeaddress, const T(&data)[N])
{
return WriteData(writeaddress, data, nullptr);
}
/**
* Write a repeated byte to an arbitrary address.
* @param address [in] Address.
* @param data [in] Byte to write.
* @param byteswritten [out, opt] Number of bytes written.
* @return Nonzero on success; 0 on error (check GetLastError()).
*/
template <int count>
static inline BOOL WriteData(void *address, const char data, SIZE_T *byteswritten)
{
char buf[count];
memset(buf, data, count);
int result = WriteData(address, buf, count, byteswritten);
return result;
}
/**
* Write a repeated byte to an arbitrary address.
* @param address [in] Address.
* @param data [in] Byte to write.
* @return Nonzero on success; 0 on error (check GetLastError()).
*/
template <int count>
static inline BOOL WriteData(void *address, char data)
{
return WriteData<count>(address, data, nullptr);
}
#if (defined(__i386__) || defined(_M_IX86)) && \
!(defined(__x86_64__) || defined(_M_X64))
/**
* Write a JMP instruction to an arbitrary address.
* @param writeaddress Address to insert the JMP instruction.
* @param funcaddress Address to JMP to.
* @return Nonzero on success; 0 on error (check GetLastError()).
*/
static inline BOOL WriteJump(void *writeaddress, void *funcaddress)
{
uint8_t data[5];
data[0] = 0xE9; // JMP DWORD (relative)
*(int32_t*)(data + 1) = (uint32_t)funcaddress - ((uint32_t)writeaddress + 5);
return WriteData(writeaddress, data);
}
/**
* Write a CALL instruction to an arbitrary address.
* @param writeaddress Address to insert the CALL instruction.
* @param funcaddress Address to CALL.
* @return Nonzero on success; 0 on error (check GetLastError()).
*/
static inline BOOL WriteCall(void *writeaddress, void *funcaddress)
{
uint8_t data[5];
data[0] = 0xE8; // CALL DWORD (relative)
*(int32_t*)(data + 1) = (uint32_t)funcaddress - ((uint32_t)writeaddress + 5);
return WriteData(writeaddress, data);
}
#endif
// Data pointer and array declarations.
#define DataPointer(type, name, address) \
static type &name = *(type *)address
#define DataArray(type, name, address, length) \
static type *const name = (type *)address; static const int name##_Length = length
// Function pointer declarations.
#define FunctionPointer(RETURN_TYPE, NAME, ARGS, ADDRESS) \
static RETURN_TYPE (__cdecl *const NAME)ARGS = (RETURN_TYPE (__cdecl *)ARGS)ADDRESS
#define StdcallFunctionPointer(RETURN_TYPE, NAME, ARGS, ADDRESS) \
static RETURN_TYPE (__stdcall *const NAME)ARGS = (RETURN_TYPE (__stdcall *)ARGS)ADDRESS
#define FastcallFunctionPointer(RETURN_TYPE, NAME, ARGS, ADDRESS) \
static RETURN_TYPE (__fastcall *const NAME)ARGS = (RETURN_TYPE (__fastcall *)ARGS)ADDRESS
#define ThiscallFunctionPointer(RETURN_TYPE, NAME, ARGS, ADDRESS) \
static RETURN_TYPE (__thiscall *const NAME)ARGS = (RETURN_TYPE (__thiscall *)ARGS)ADDRESS
#define VoidFunc(NAME, ADDRESS) FunctionPointer(void,NAME,(void),ADDRESS)
// Non-static FunctionPointer.
// If declaring a FunctionPointer within a function, use this one instead.
// Otherwise, the program will crash on Windows XP.
#define NonStaticFunctionPointer(RETURN_TYPE, NAME, ARGS, ADDRESS) \
RETURN_TYPE (__cdecl *const NAME)ARGS = (RETURN_TYPE (__cdecl *)ARGS)ADDRESS
#define patchdecl(address,data) { (void*)address, arrayptrandsize(data) }
#define ptrdecl(address,data) { (void*)address, (void*)data }
#endif /* MODLOADER_MEMACCESS_H */