Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
axstin
GitHub Repository: axstin/rbxfpsunlocker
Path: blob/master/Source/procutil.h
259 views
1
#pragma once
2
3
#include <Windows.h>
4
#include <Psapi.h>
5
6
#include <vector>
7
#include <string>
8
#include <filesystem>
9
#include <optional>
10
#include <memory>
11
12
#define PAGE_READABLE (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_READONLY | PAGE_READWRITE)
13
14
namespace ProcUtil
15
{
16
// Problem: Calling GetLastError() in a catch block is sketchy/unreliable as Windows' internal exception handling _may_ call WinAPI functions beforehand that change the error. Better safe than sorry.
17
// Solution: This class
18
class WindowsException : public std::runtime_error
19
{
20
public:
21
WindowsException(const char *message)
22
: std::runtime_error(init(message))
23
{
24
}
25
26
DWORD GetLastError() const
27
{
28
return last_error;
29
}
30
31
private:
32
const char *init(const char *message)
33
{
34
last_error = ::GetLastError();
35
return message;
36
}
37
38
DWORD last_error;
39
};
40
41
struct ScopedHandle
42
{
43
HANDLE value = NULL;
44
45
ScopedHandle(HANDLE value) : value(value) {}
46
ScopedHandle(const ScopedHandle &) = delete;
47
ScopedHandle &operator=(const ScopedHandle &) = delete;
48
49
ScopedHandle(ScopedHandle &&other) noexcept
50
{
51
std::swap(value, other.value);
52
}
53
54
ScopedHandle &operator=(ScopedHandle &&other) noexcept
55
{
56
if (this != &other)
57
{
58
Close();
59
std::swap(value, other.value);
60
}
61
return *this;
62
}
63
64
bool IsOpen() const { return value != NULL; }
65
explicit operator bool() const { return IsOpen(); }
66
operator HANDLE() const { return value; }
67
68
void Close()
69
{
70
if (value)
71
{
72
CloseHandle(value);
73
value = NULL;
74
}
75
}
76
77
~ScopedHandle()
78
{
79
Close();
80
}
81
};
82
83
struct ModuleInfo;
84
struct ProcessInfo;
85
86
std::vector<DWORD> GetProcessIdsByImageName(const char *image_name, size_t limit = -1);
87
std::vector<HANDLE> GetProcessesByImageName(const char *image_name, DWORD access, size_t limit = -1);
88
HANDLE GetProcessByImageName(const char* image_name);
89
90
std::vector<ModuleInfo> GetProcessModules(DWORD process_id, size_t limit = -1);
91
ModuleInfo GetMainModuleInfo(HANDLE process);
92
bool FindModuleInfo(HANDLE process, const std::filesystem::path& name, ModuleInfo& out);
93
void *ScanProcess(HANDLE process, const char *aob, const char *mask, const uint8_t *start = nullptr, const uint8_t *end = (const uint8_t *)UINTPTR_MAX);
94
95
bool IsOS64Bit();
96
bool IsProcess64Bit(HANDLE process);
97
98
template <typename T>
99
inline bool Read(HANDLE process, const void *location, T *buffer, size_t size = 1) noexcept
100
{
101
return ReadProcessMemory(process, location, buffer, size * sizeof(T), NULL) != 0;
102
}
103
104
template <typename T>
105
inline T Read(HANDLE process, const void *location)
106
{
107
T value;
108
if (!ReadProcessMemory(process, location, (LPVOID) &value, sizeof(T), NULL)) throw WindowsException("unable to read process memory");
109
return value;
110
}
111
112
inline const void *ReadPointer(HANDLE process, const void *location)
113
{
114
#ifdef _WIN64
115
return IsProcess64Bit(process) ? (const void *)Read<uint64_t>(process, location) : (const void *)Read<uint32_t>(process, location);
116
#else
117
return Read<const void *>(process, location);
118
#endif
119
}
120
121
template <typename T>
122
inline void Write(HANDLE process, const void *location, const T& value)
123
{
124
if (!WriteProcessMemory(process, (LPVOID) location, (LPCVOID) &value, sizeof(T), NULL)) throw WindowsException("unable to write process memory");
125
}
126
127
struct ModuleInfo
128
{
129
std::filesystem::path path;
130
void *base = nullptr;
131
size_t size = 0;
132
133
HMODULE GetHandle() const
134
{
135
return (HMODULE)base;
136
}
137
};
138
139
// todo: ew. refactor
140
struct ProcessInfo
141
{
142
HANDLE handle = NULL;
143
ModuleInfo module;
144
145
DWORD id = 0;
146
std::string name;
147
148
HWND window = NULL;
149
std::string window_title;
150
151
bool FindMainWindow() // a.k.a. find first window associated with the process that is visible
152
{
153
window = NULL;
154
155
EnumWindows([](HWND window, LPARAM param) -> BOOL
156
{
157
auto info = (ProcessInfo *)param;
158
159
DWORD process_id;
160
GetWindowThreadProcessId(window, &process_id);
161
162
if (IsWindowVisible(window) && process_id == info->id)
163
{
164
char title[256] = { 0 };
165
GetWindowTextA(window, title, sizeof(title));
166
167
info->window = window;
168
info->window_title = title;
169
return FALSE;
170
}
171
172
return TRUE;
173
}, (LPARAM)this);
174
175
return window != NULL;
176
}
177
178
ProcessInfo()
179
{}
180
181
ProcessInfo(HANDLE handle, bool find_window = false)
182
: handle(handle), window(NULL)
183
{
184
id = GetProcessId(handle);
185
module = GetMainModuleInfo(handle);
186
name = module.path.filename().string();
187
188
if (find_window)
189
FindMainWindow();
190
}
191
};
192
}
193