mirror of
https://github.com/ineedbots/cod2m.git
synced 2025-03-15 11:36:56 +00:00
Added base scheduler
This commit is contained in:
parent
ff04c81ddd
commit
fbeca33cfb
@ -3,12 +3,162 @@
|
|||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
|
bool Scheduler::AsyncTerminate;
|
||||||
|
std::thread Scheduler::AsyncThread;
|
||||||
|
|
||||||
|
bool Scheduler::ReadyPassed = false;
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::ReadySignal;
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::ShutdownSignal;
|
||||||
|
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::FrameSignal;
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::FrameOnceSignal;
|
||||||
|
std::vector<Scheduler::DelayedSlot> Scheduler::DelayedSlots;
|
||||||
|
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::AsyncFrameSignal;
|
||||||
|
Utils::Signal<Scheduler::Callback> Scheduler::AsyncFrameOnceSignal;
|
||||||
|
|
||||||
|
void Scheduler::Once(Utils::Slot<Scheduler::Callback> callback, bool clientOnly)
|
||||||
|
{
|
||||||
|
if (clientOnly && Game::IsDedicated()) return;
|
||||||
|
Scheduler::FrameOnceSignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnShutdown(Utils::Slot<Scheduler::Callback> callback)
|
||||||
|
{
|
||||||
|
Scheduler::ShutdownSignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnFrame(Utils::Slot<Scheduler::Callback> callback, bool clientOnly)
|
||||||
|
{
|
||||||
|
if (clientOnly && Game::IsDedicated()) return;
|
||||||
|
Scheduler::FrameSignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnReady(Utils::Slot<Scheduler::Callback> callback, bool clientOnly)
|
||||||
|
{
|
||||||
|
if (clientOnly && Game::IsDedicated()) return;
|
||||||
|
if (Scheduler::ReadyPassed) Scheduler::Once(callback);
|
||||||
|
else Scheduler::ReadySignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::ReadyHandler()
|
||||||
|
{
|
||||||
|
if (!false)
|
||||||
|
{
|
||||||
|
Scheduler::Once(Scheduler::ReadyHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Scheduler::ReadyPassed = true;
|
||||||
|
Scheduler::ReadySignal();
|
||||||
|
Scheduler::ReadySignal.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::FrameHandler()
|
||||||
|
{
|
||||||
|
Scheduler::DelaySignal();
|
||||||
|
Scheduler::FrameSignal();
|
||||||
|
|
||||||
|
Utils::Signal<Scheduler::Callback> copy(Scheduler::FrameOnceSignal);
|
||||||
|
Scheduler::FrameOnceSignal.clear();
|
||||||
|
copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnDelay(Utils::Slot<Scheduler::Callback> callback, std::chrono::nanoseconds delay, bool clientOnly)
|
||||||
|
{
|
||||||
|
if (clientOnly && Game::IsDedicated()) return;
|
||||||
|
|
||||||
|
Scheduler::DelayedSlot slot;
|
||||||
|
slot.callback = callback;
|
||||||
|
slot.delay = delay;
|
||||||
|
|
||||||
|
Scheduler::DelayedSlots.push_back(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::DelaySignal()
|
||||||
|
{
|
||||||
|
Utils::Signal<Scheduler::Callback> signal;
|
||||||
|
|
||||||
|
for (auto i = Scheduler::DelayedSlots.begin(); i != Scheduler::DelayedSlots.end();)
|
||||||
|
{
|
||||||
|
if (i->interval.elapsed(i->delay))
|
||||||
|
{
|
||||||
|
signal.connect(i->callback);
|
||||||
|
i = Scheduler::DelayedSlots.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::ShutdownStub(int num)
|
||||||
|
{
|
||||||
|
Scheduler::ShutdownSignal();
|
||||||
|
//Utils::Hook::Call<void(int)>(0x46B370)(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnFrameAsync(Utils::Slot<Scheduler::Callback> callback)
|
||||||
|
{
|
||||||
|
Scheduler::AsyncFrameSignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::OnceAsync(Utils::Slot<Scheduler::Callback> callback)
|
||||||
|
{
|
||||||
|
Scheduler::AsyncFrameOnceSignal.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
Scheduler::Scheduler()
|
Scheduler::Scheduler()
|
||||||
{
|
{
|
||||||
//MessageBoxA(nullptr, Utils::String::VA("%d", Game::svs), "DEBUG", 0);
|
Scheduler::ReadyPassed = false;
|
||||||
|
Scheduler::Once(Scheduler::ReadyHandler);
|
||||||
|
|
||||||
|
// hook frames,
|
||||||
|
//Utils::Hook(0x4D697A, Scheduler::ShutdownStub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
if (!Loader::IsPerformingUnitTests())
|
||||||
|
{
|
||||||
|
Scheduler::AsyncTerminate = false;
|
||||||
|
Scheduler::AsyncThread = std::thread([]()
|
||||||
|
{
|
||||||
|
while (!Scheduler::AsyncTerminate)
|
||||||
|
{
|
||||||
|
Scheduler::AsyncFrameSignal();
|
||||||
|
|
||||||
|
Utils::Signal<Scheduler::Callback> copy(Scheduler::AsyncFrameOnceSignal);
|
||||||
|
Scheduler::AsyncFrameOnceSignal.clear();
|
||||||
|
copy();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(16ms);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheduler::~Scheduler()
|
Scheduler::~Scheduler()
|
||||||
{
|
{
|
||||||
|
Scheduler::ReadySignal.clear();
|
||||||
|
Scheduler::ShutdownSignal.clear();
|
||||||
|
|
||||||
|
Scheduler::FrameSignal.clear();
|
||||||
|
Scheduler::FrameOnceSignal.clear();
|
||||||
|
Scheduler::DelayedSlots.clear();
|
||||||
|
|
||||||
|
Scheduler::AsyncFrameSignal.clear();
|
||||||
|
Scheduler::AsyncFrameOnceSignal.clear();
|
||||||
|
|
||||||
|
Scheduler::ReadyPassed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::preDestroy()
|
||||||
|
{
|
||||||
|
Scheduler::AsyncTerminate = true;
|
||||||
|
if (Scheduler::AsyncThread.joinable())
|
||||||
|
{
|
||||||
|
Scheduler::AsyncThread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,50 @@ namespace Components
|
|||||||
class Scheduler : public Component
|
class Scheduler : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef void(Callback)();
|
||||||
|
|
||||||
Scheduler();
|
Scheduler();
|
||||||
~Scheduler();
|
~Scheduler();
|
||||||
|
|
||||||
|
void preDestroy() override;
|
||||||
|
|
||||||
|
static void OnShutdown(Utils::Slot<Callback> callback);
|
||||||
|
static void OnFrame(Utils::Slot<Callback> callback, bool clientOnly = false);
|
||||||
|
static void OnReady(Utils::Slot<Callback> callback, bool clientOnly = false);
|
||||||
|
static void Once(Utils::Slot<Callback> callback, bool clientOnly = false);
|
||||||
|
static void OnDelay(Utils::Slot<Callback> callback, std::chrono::nanoseconds delay, bool clientOnly = false);
|
||||||
|
|
||||||
|
static void OnFrameAsync(Utils::Slot<Callback> callback);
|
||||||
|
static void OnceAsync(Utils::Slot<Callback> callback);
|
||||||
|
|
||||||
|
static void FrameHandler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class DelayedSlot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::chrono::nanoseconds delay;
|
||||||
|
Utils::Time::Interval interval;
|
||||||
|
Utils::Slot<Callback> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool AsyncTerminate;
|
||||||
|
static std::thread AsyncThread;
|
||||||
|
|
||||||
|
static Utils::Signal<Callback> FrameSignal;
|
||||||
|
static Utils::Signal<Callback> FrameOnceSignal;
|
||||||
|
static std::vector<DelayedSlot> DelayedSlots;
|
||||||
|
|
||||||
|
static bool ReadyPassed;
|
||||||
|
static Utils::Signal<Callback> ReadySignal;
|
||||||
|
static Utils::Signal<Callback> ShutdownSignal;
|
||||||
|
|
||||||
|
static Utils::Signal<Callback> AsyncFrameSignal;
|
||||||
|
static Utils::Signal<Callback> AsyncFrameOnceSignal;
|
||||||
|
|
||||||
|
static void ReadyHandler();
|
||||||
|
static void DelaySignal();
|
||||||
|
|
||||||
|
static void ShutdownStub(int num);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,12 @@ namespace Game
|
|||||||
Player_GetMethod_t* Player_GetMethod;
|
Player_GetMethod_t* Player_GetMethod;
|
||||||
GScr_LoadGameTypeScript_t* GScr_LoadGameTypeScript;
|
GScr_LoadGameTypeScript_t* GScr_LoadGameTypeScript;
|
||||||
G_LoadStructs_t* G_LoadStructs;
|
G_LoadStructs_t* G_LoadStructs;
|
||||||
|
Sys_Milliseconds_t* Sys_Milliseconds;
|
||||||
|
|
||||||
|
bool IsDedicated()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Init(GAMEEXE)
|
void Init(GAMEEXE)
|
||||||
{
|
{
|
||||||
@ -41,6 +47,7 @@ namespace Game
|
|||||||
Scr_LoadScript = ASSIGN(Scr_LoadScript_t*, 0x474D80);
|
Scr_LoadScript = ASSIGN(Scr_LoadScript_t*, 0x474D80);
|
||||||
GScr_LoadGameTypeScript = ASSIGN(GScr_LoadGameTypeScript_t*, 0x503F90);
|
GScr_LoadGameTypeScript = ASSIGN(GScr_LoadGameTypeScript_t*, 0x503F90);
|
||||||
G_LoadStructs = ASSIGN(G_LoadStructs_t*, 0x5118A0);
|
G_LoadStructs = ASSIGN(G_LoadStructs_t*, 0x5118A0);
|
||||||
|
Sys_Milliseconds = ASSIGN(Sys_Milliseconds_t*, 0x435200);
|
||||||
|
|
||||||
|
|
||||||
cls = ASSIGN(clientStatic_t*, 0x68A408);
|
cls = ASSIGN(clientStatic_t*, 0x68A408);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
void Init(GAMEEXE);
|
void Init(GAMEEXE);
|
||||||
|
bool IsDedicated();
|
||||||
|
|
||||||
extern clientStatic_t* cls;
|
extern clientStatic_t* cls;
|
||||||
extern serverStatic_t* svs;
|
extern serverStatic_t* svs;
|
||||||
@ -42,6 +43,9 @@ namespace Game
|
|||||||
typedef void (G_LoadStructs_t)();
|
typedef void (G_LoadStructs_t)();
|
||||||
extern G_LoadStructs_t* G_LoadStructs;
|
extern G_LoadStructs_t* G_LoadStructs;
|
||||||
|
|
||||||
|
typedef int (Sys_Milliseconds_t)();
|
||||||
|
extern Sys_Milliseconds_t* Sys_Milliseconds;
|
||||||
|
|
||||||
extern unsigned int Scr_GetFunctionHandle(char*, const char*);
|
extern unsigned int Scr_GetFunctionHandle(char*, const char*);
|
||||||
extern __int16 Scr_ExecThread(int);
|
extern __int16 Scr_ExecThread(int);
|
||||||
extern void RemoveRefToObject(int);
|
extern void RemoveRefToObject(int);
|
||||||
|
@ -90,6 +90,8 @@ enum GAMEEXE
|
|||||||
#include "Utils/Hooking.hpp"
|
#include "Utils/Hooking.hpp"
|
||||||
#include "Utils/Memory.hpp"
|
#include "Utils/Memory.hpp"
|
||||||
#include "Utils/String.hpp"
|
#include "Utils/String.hpp"
|
||||||
|
#include "Utils/Time.hpp"
|
||||||
|
#include "Utils/Utils.hpp"
|
||||||
|
|
||||||
#include "Game/Structs.hpp"
|
#include "Game/Structs.hpp"
|
||||||
#include "Game/Game.hpp"
|
#include "Game/Game.hpp"
|
||||||
|
42
src/Utils/Time.cpp
Normal file
42
src/Utils/Time.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
namespace Time
|
||||||
|
{
|
||||||
|
void Interval::update()
|
||||||
|
{
|
||||||
|
this->lastPoint = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Interval::elapsed(std::chrono::nanoseconds nsecs)
|
||||||
|
{
|
||||||
|
return ((std::chrono::high_resolution_clock::now() - this->lastPoint) >= nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point::Point() : lastPoint(Game::Sys_Milliseconds())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::update()
|
||||||
|
{
|
||||||
|
this->lastPoint = Game::Sys_Milliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Point::diff(Point point)
|
||||||
|
{
|
||||||
|
return point.lastPoint - this->lastPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Point::after(Point point)
|
||||||
|
{
|
||||||
|
return this->diff(point) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Point::elapsed(int milliseconds)
|
||||||
|
{
|
||||||
|
return (Game::Sys_Milliseconds() - this->lastPoint) >= milliseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/Utils/Time.hpp
Normal file
33
src/Utils/Time.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
namespace Time
|
||||||
|
{
|
||||||
|
class Interval
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::chrono::high_resolution_clock::time_point lastPoint;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Interval() : lastPoint(std::chrono::high_resolution_clock::now()) {}
|
||||||
|
|
||||||
|
void update();
|
||||||
|
bool elapsed(std::chrono::nanoseconds nsecs);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Point
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Point();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
int diff(Point point);
|
||||||
|
bool after(Point point);
|
||||||
|
bool elapsed(int milliseconds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int lastPoint;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
148
src/Utils/Utils.cpp
Normal file
148
src/Utils/Utils.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
std::string GetMimeType(const std::string& url)
|
||||||
|
{
|
||||||
|
wchar_t* mimeType = nullptr;
|
||||||
|
FindMimeFromData(nullptr, std::wstring(url.begin(), url.end()).data(), nullptr, 0, nullptr, 0, &mimeType, 0);
|
||||||
|
|
||||||
|
if (mimeType)
|
||||||
|
{
|
||||||
|
std::wstring wMimeType(mimeType);
|
||||||
|
return std::string(wMimeType.begin(), wMimeType.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ParseChallenge(const std::string& data)
|
||||||
|
{
|
||||||
|
auto pos = data.find_first_of("\n ");
|
||||||
|
if (pos == std::string::npos) return data;
|
||||||
|
return data.substr(0, pos).data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputDebugLastError()
|
||||||
|
{
|
||||||
|
DWORD errorMessageID = ::GetLastError();
|
||||||
|
OutputDebugStringA(Utils::String::VA("Last error code: 0x%08X (%s)\n", errorMessageID, GetLastWindowsError().data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetLastWindowsError()
|
||||||
|
{
|
||||||
|
DWORD errorMessageID = ::GetLastError();
|
||||||
|
LPSTR messageBuffer = nullptr;
|
||||||
|
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
nullptr, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&messageBuffer), 0, nullptr);
|
||||||
|
std::string message(messageBuffer, size);
|
||||||
|
LocalFree(messageBuffer);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsWineEnvironment()
|
||||||
|
{
|
||||||
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
|
if (!hntdll) return false;
|
||||||
|
|
||||||
|
return (GetProcAddress(hntdll, "wine_get_version") != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long GetParentProcessId()
|
||||||
|
{
|
||||||
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;
|
||||||
|
|
||||||
|
Utils::Memory::Allocator allocator;
|
||||||
|
allocator.reference(hSnapshot, [](void* handle) { CloseHandle(handle); });
|
||||||
|
|
||||||
|
PROCESSENTRY32 pe32;
|
||||||
|
ZeroMemory(&pe32, sizeof(pe32));
|
||||||
|
pe32.dwSize = sizeof(pe32);
|
||||||
|
|
||||||
|
DWORD pid = GetCurrentProcessId();
|
||||||
|
while (Process32Next(hSnapshot, &pe32))
|
||||||
|
{
|
||||||
|
if (pe32.th32ProcessID == pid)
|
||||||
|
{
|
||||||
|
return pe32.th32ParentProcessID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetModuleSize(HMODULE module)
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER header = PIMAGE_DOS_HEADER(module);
|
||||||
|
PIMAGE_NT_HEADERS ntHeader = PIMAGE_NT_HEADERS(DWORD(module) + header->e_lfanew);
|
||||||
|
return ntHeader->OptionalHeader.SizeOfImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetThreadStartAddress(HANDLE hThread)
|
||||||
|
{
|
||||||
|
HMODULE ntdll = Utils::GetNTDLL();
|
||||||
|
if (!ntdll) return nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t ntQueryInformationThread[] = { 0xB1, 0x8B, 0xAE, 0x8A, 0x9A, 0x8D, 0x86, 0xB6, 0x91, 0x99, 0x90, 0x8D, 0x92, 0x9E, 0x8B, 0x96, 0x90, 0x91, 0xAB, 0x97, 0x8D, 0x9A, 0x9E, 0x9B }; // NtQueryInformationThread
|
||||||
|
NtQueryInformationThread_t NtQueryInformationThread = NtQueryInformationThread_t(GetProcAddress(ntdll, Utils::String::XOR(std::string(reinterpret_cast<char*>(ntQueryInformationThread), sizeof ntQueryInformationThread), -1).data()));
|
||||||
|
if (!NtQueryInformationThread) return nullptr;
|
||||||
|
|
||||||
|
HANDLE dupHandle, currentProcess = GetCurrentProcess();
|
||||||
|
if (!DuplicateHandle(currentProcess, hThread, currentProcess, &dupHandle, THREAD_QUERY_INFORMATION, FALSE, 0))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_ACCESS_DENIED);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* address = nullptr;
|
||||||
|
NTSTATUS status = NtQueryInformationThread(dupHandle, ThreadQuerySetWin32StartAddress, &address, sizeof(address), nullptr);
|
||||||
|
CloseHandle(dupHandle);
|
||||||
|
|
||||||
|
if (status != 0) return nullptr;
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetEnvironment()
|
||||||
|
{
|
||||||
|
wchar_t exeName[512];
|
||||||
|
GetModuleFileName(GetModuleHandle(nullptr), exeName, sizeof(exeName) / 2);
|
||||||
|
|
||||||
|
wchar_t* exeBaseName = wcsrchr(exeName, L'\\');
|
||||||
|
exeBaseName[0] = L'\0';
|
||||||
|
|
||||||
|
SetCurrentDirectory(exeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE GetNTDLL()
|
||||||
|
{
|
||||||
|
static uint8_t ntdll[] = { 0x91, 0x8B, 0x9B, 0x93, 0x93, 0xD1, 0x9B, 0x93, 0x93 }; // ntdll.dll
|
||||||
|
return GetModuleHandleA(Utils::String::XOR(std::string(reinterpret_cast<char*>(ntdll), sizeof ntdll), -1).data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SafeShellExecute(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
|
||||||
|
{
|
||||||
|
[=]()
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
ShellExecuteA(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd);
|
||||||
|
}
|
||||||
|
__finally
|
||||||
|
{}
|
||||||
|
}();
|
||||||
|
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenUrl(const std::string& url)
|
||||||
|
{
|
||||||
|
SafeShellExecute(nullptr, "open", url.data(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasIntercection(unsigned int base1, unsigned int len1, unsigned int base2, unsigned int len2)
|
||||||
|
{
|
||||||
|
return !(base1 + len1 <= base2 || base2 + len2 <= base1);
|
||||||
|
}
|
||||||
|
}
|
129
src/Utils/Utils.hpp
Normal file
129
src/Utils/Utils.hpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef LONG NTSTATUS;
|
||||||
|
typedef NTSTATUS(NTAPI *NtCreateThreadEx_t)(PHANDLE hThread, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD StackZeroBits, DWORD SizeOfStackCommit, DWORD SizeOfStackReserve, LPVOID lpBytesBuffer);
|
||||||
|
typedef NTSTATUS(NTAPI* NtQueryInformationThread_t)(HANDLE ThreadHandle, LONG ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength);
|
||||||
|
#define ThreadQuerySetWin32StartAddress 9
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
std::string GetMimeType(const std::string& url);
|
||||||
|
std::string ParseChallenge(const std::string& data);
|
||||||
|
void OutputDebugLastError();
|
||||||
|
std::string GetLastWindowsError();
|
||||||
|
|
||||||
|
bool IsWineEnvironment();
|
||||||
|
|
||||||
|
unsigned long GetParentProcessId();
|
||||||
|
size_t GetModuleSize(HMODULE);
|
||||||
|
void* GetThreadStartAddress(HANDLE hThread);
|
||||||
|
HMODULE GetNTDLL();
|
||||||
|
|
||||||
|
void SetEnvironment();
|
||||||
|
|
||||||
|
void OpenUrl(const std::string& url);
|
||||||
|
|
||||||
|
bool HasIntercection(unsigned int base1, unsigned int len1, unsigned int base2, unsigned int len2);
|
||||||
|
|
||||||
|
template <typename T> inline void RotLeft(T& object, size_t bits)
|
||||||
|
{
|
||||||
|
bits %= sizeof(T) * 8;
|
||||||
|
|
||||||
|
T sign = 1;
|
||||||
|
sign = sign << (sizeof(T) * 8 - 1);
|
||||||
|
|
||||||
|
bool negative = (object & sign) != 0;
|
||||||
|
object &= ~sign;
|
||||||
|
object = (object << bits) | (object >> (sizeof(T) * 8 - bits));
|
||||||
|
object |= T(negative) << ((sizeof(T) * 8 - 1 + bits) % (sizeof(T) * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline void RotRight(T& object, size_t bits)
|
||||||
|
{
|
||||||
|
bits %= (sizeof(T) * 8);
|
||||||
|
RotLeft<T>(object, ((sizeof(T) * 8) - bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length)
|
||||||
|
{
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
target->push_back(source[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline void Merge(std::vector<T>* target, std::vector<T> source)
|
||||||
|
{
|
||||||
|
for (auto &entry : source)
|
||||||
|
{
|
||||||
|
target->push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> using Slot = std::function<T>;
|
||||||
|
template <typename T>
|
||||||
|
class Signal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Signal()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(this->mutex);
|
||||||
|
|
||||||
|
this->slots.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Signal(Signal& obj) : Signal()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(this->mutex);
|
||||||
|
std::lock_guard<std::recursive_mutex> __(obj.mutex);
|
||||||
|
|
||||||
|
Utils::Merge(&this->slots, obj.getSlots());
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect(Slot<T> slot)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(this->mutex);
|
||||||
|
|
||||||
|
if (slot)
|
||||||
|
{
|
||||||
|
this->slots.push_back(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(this->mutex);
|
||||||
|
|
||||||
|
this->slots.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Slot<T>>& getSlots()
|
||||||
|
{
|
||||||
|
return this->slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ...Args>
|
||||||
|
void operator()(Args&&... args) const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(this->mutex);
|
||||||
|
|
||||||
|
std::vector<Slot<T>> copiedSlots;
|
||||||
|
Utils::Merge(&copiedSlots, this->slots);
|
||||||
|
|
||||||
|
for (auto& slot : copiedSlots)
|
||||||
|
{
|
||||||
|
if (slot)
|
||||||
|
{
|
||||||
|
slot(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::recursive_mutex mutex;
|
||||||
|
std::vector<Slot<T>> slots;
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user