1
0
mirror of synced 2024-11-11 22:07:09 +01:00

VS 2019 compilation ok

This commit is contained in:
Reaver 2019-06-03 19:25:47 +03:00
parent 2f02d74d26
commit d130815f0d
7 changed files with 609 additions and 597 deletions

View File

@ -2,6 +2,7 @@
#include <Utility/InitFunction.h> #include <Utility/InitFunction.h>
#include "Global.h" #include "Global.h"
#include "Utility/GameDetect.h" #include "Utility/GameDetect.h"
#include "Utility/Hooking.Patterns.h"
#pragma optimize("", off) #pragma optimize("", off)
void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3) void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3)
@ -190,9 +191,51 @@ void init_windowHooks(windowHooks* data)
} }
/* END WINDOW HOOKS */ /* END WINDOW HOOKS */
void InitializeHints()
{
static std::string modPath;
if (modPath.empty())
{
char exeName[512];
GetModuleFileNameA(GetModuleHandle(NULL), exeName, sizeof(exeName));
char* exeBaseName = strrchr(exeName, '\\');
exeBaseName[0] = L'\0';
modPath = exeName;
modPath += "\\";
GetFullPathNameA(modPath.c_str(), sizeof(exeName), exeName, nullptr);
modPath = exeName;
modPath += "\\";
}
std::string hintsFile = modPath + "hints.dat";
FILE* hints = fopen(hintsFile.c_str(), "rb");
if (hints)
{
while (!feof(hints))
{
uint64_t hash;
uintptr_t hint;
fread(&hash, 1, sizeof(hash), hints);
fread(&hint, 1, sizeof(hint), hints);
hook::pattern::hint(hash, hint);
}
fclose(hints);
}
}
static InitFunction globalFunc([]() static InitFunction globalFunc([]()
{ {
InitializeHints();
CreateThread(NULL, 0, QuitGameThread, NULL, 0, NULL); CreateThread(NULL, 0, QuitGameThread, NULL, 0, NULL);
}, GameID::Global); }, GameID::Global);
#pragma optimize("", on) #pragma optimize("", on)

View File

@ -1,350 +1,361 @@
/* /*
* This file is part of the CitizenFX project - http://citizen.re/ * This file is part of the CitizenFX project - http://citizen.re/
* *
* See LICENSE and MENTIONS in the root of the source tree for information * See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing. * regarding licensing.
*/ */
#include "Hooking.Patterns.h" #include "StdInc.h"
#define WIN32_LEAN_AND_MEAN #ifdef min
#undef min
#include <windows.h> #endif
#include <algorithm>
#ifdef max
#if PATTERNS_USE_HINTS #undef max
#include <map> #endif
#endif
#include "Hooking.Patterns.h"
#if PATTERNS_USE_HINTS
#include <algorithm>
// from boost someplace #include <string_view>
template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
struct basic_fnv_1 #if PATTERNS_USE_HINTS
{ #include <map>
std::uint64_t operator()(const char *text) const
{ static void Citizen_PatternSaveHint(uint64_t hash, uintptr_t hint)
std::uint64_t hash = OffsetBasis; {
static std::string modPath;
while (*text != 0)
{ if (modPath.empty())
hash *= FnvPrime; {
hash ^= *(uint8_t *)text; char exeName[512];
GetModuleFileNameA(GetModuleHandle(NULL), exeName, sizeof(exeName));
++text;
} char* exeBaseName = strrchr(exeName, '\\');
exeBaseName[0] = L'\0';
return hash;
} modPath = exeName;
}; modPath += "\\";
const std::uint64_t fnv_prime = 1099511628211u; GetFullPathNameA(modPath.c_str(), sizeof(exeName), exeName, nullptr);
const std::uint64_t fnv_offset_basis = 14695981039346656037u;
modPath = exeName;
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1; modPath += "\\";
}
#endif
std::string hintsFile = modPath + "hints.dat";
namespace hook
{ FILE* hints = fopen(hintsFile.c_str(), "ab");
ptrdiff_t baseAddressDifference;
if (hints)
// sets the base to the process main base {
void set_base() fwrite(&hash, 1, sizeof(hash), hints);
{ fwrite(&hint, 1, sizeof(hint), hints);
set_base((uintptr_t)GetModuleHandle(nullptr));
} fclose(hints);
}
}
#if PATTERNS_USE_HINTS #endif
static std::multimap<uint64_t, uintptr_t> g_hints;
#endif
#if PATTERNS_USE_HINTS
static void TransformPattern(const char *pattern, std::vector<uint8_t>& data, std::vector<uint8_t>& mask)
{ // from boost someplace
auto tol = [](char ch) -> uint8_t template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
{ struct basic_fnv_1
if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10); {
if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10); std::uint64_t operator()(std::string_view text) const
return uint8_t(ch - '0'); {
}; std::uint64_t hash = OffsetBasis;
for (auto it : text)
auto is_digit = [](char ch) -> bool {
{ hash *= FnvPrime;
return (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9'); hash ^= it;
}; }
char temp_string[2]{ 0, 0 }; return hash;
}
data.clear(); };
mask.clear();
const std::uint64_t fnv_prime = 1099511628211u;
if (!pattern) const std::uint64_t fnv_offset_basis = 14695981039346656037u;
{
return; typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
}
#endif
const char *patit = pattern;
const char *patend = (pattern + strlen(pattern) + 1); namespace hook
{
while (patit != patend) inline std::multimap<uint64_t, uintptr_t>& GetHints()
{ {
char ch = *patit; static std::multimap<uint64_t, uintptr_t> hints;
return hints;
if (ch == ' ' || ch == 0) }
{
if (!temp_string[0] && !temp_string[1]) //Continous delimiter static void TransformPattern(std::string_view pattern, std::string& data, std::string& mask)
{ {
uint8_t tempDigit = 0;
} bool tempFlag = false;
else if (temp_string[0] == '?' && (temp_string[1] == '?' || temp_string[1] == 0)) //??
{ auto tol = [](char ch) -> uint8_t
data.push_back(0); {
mask.push_back(0u); if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10);
} if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10);
else if (temp_string[0] == '?' && is_digit(temp_string[1])) //?x return uint8_t(ch - '0');
{ };
data.push_back(tol(temp_string[1]));
mask.push_back(0x0Fu); for (auto ch : pattern)
} {
else if (temp_string[1] == '?' && is_digit(temp_string[0])) //x? if (ch == ' ')
{ {
data.push_back(tol(temp_string[0]) << 4); continue;
mask.push_back(0xF0u); }
} else if (ch == '?')
else if (is_digit(temp_string[0]) && is_digit(temp_string[1])) //xx {
{ data.push_back(0);
data.push_back((tol(temp_string[0]) << 4) | tol(temp_string[1])); mask.push_back('?');
mask.push_back(0xFFu); }
} else if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'))
else {
{ uint8_t thisDigit = tol(ch);
data.clear();
mask.clear(); if (!tempFlag)
return; {
} tempDigit = thisDigit << 4;
tempFlag = true;
temp_string[0] = 0; }
temp_string[1] = 0; else
} {
else tempDigit |= thisDigit;
{ tempFlag = false;
if (temp_string[0] == 0)
{ data.push_back(tempDigit);
temp_string[0] = ch; mask.push_back('x');
} }
else if (temp_string[1] == 0) }
{ }
temp_string[1] = ch; }
}
else class executable_meta
{ {
data.clear(); private:
mask.clear(); uintptr_t m_begin;
return; uintptr_t m_end;
}
} public:
template<typename TReturn, typename TOffset>
++patit; TReturn* getRVA(TOffset rva)
} {
} return (TReturn*)(m_begin + rva);
}
class executable_meta
{ explicit executable_meta(void* module)
private: : m_begin((uintptr_t)module)
uintptr_t m_begin; {
uintptr_t m_end; PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0);
PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);
public:
template<typename TReturn, typename TOffset> m_end = m_begin + ntHeader->OptionalHeader.SizeOfImage;
TReturn* getRVA(TOffset rva) }
{
return (TReturn*)(m_begin + rva); executable_meta(uintptr_t begin, uintptr_t end)
} : m_begin(begin), m_end(end)
{
explicit executable_meta(void* module) }
: m_begin((uintptr_t)module), m_end(0)
{ inline uintptr_t begin() const { return m_begin; }
static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER inline uintptr_t end() const { return m_end; }
{ };
return reinterpret_cast<PIMAGE_SECTION_HEADER>(
(UCHAR*)nt_headers->OptionalHeader.DataDirectory + void pattern::Initialize(const char* pattern, size_t length)
nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) + {
section * sizeof(IMAGE_SECTION_HEADER)); // get the hash for the base pattern
}; #if PATTERNS_USE_HINTS
m_hash = fnv_1()(std::string_view(pattern, length));
PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0); #endif
PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);
// transform the base pattern from IDA format to canonical format
for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) TransformPattern(std::string_view(pattern, length), m_bytes, m_mask);
{
auto sec = getSection(ntHeader, i); #if PATTERNS_USE_HINTS
auto secSize = sec->SizeOfRawData != 0 ? sec->SizeOfRawData : sec->Misc.VirtualSize; // if there's hints, try those first
//if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) if (m_module == GetModuleHandle(nullptr))
m_end = m_begin + sec->VirtualAddress + secSize; {
auto range = GetHints().equal_range(m_hash);
if ((i == ntHeader->FileHeader.NumberOfSections - 1) && m_end == 0)
m_end = m_begin + sec->PointerToRawData + secSize; if (range.first != range.second)
} {
} std::for_each(range.first, range.second, [&](const std::pair<uint64_t, uintptr_t>& hint)
{
executable_meta(uintptr_t begin, uintptr_t end) ConsiderMatch(hint.second);
: m_begin(begin), m_end(end) });
{
} // if the hints succeeded, we don't need to do anything more
if (!m_matches.empty())
inline uintptr_t begin() const { return m_begin; } {
inline uintptr_t end() const { return m_end; } m_matched = true;
}; return;
}
void pattern::Initialize(const char* pattern) }
{ }
// get the hash for the base pattern #endif
#if PATTERNS_USE_HINTS }
m_hash = fnv_1()(pattern);
#endif void pattern::EnsureMatches(uint32_t maxCount)
{
// transform the base pattern from IDA format to canonical format if (m_matched)
TransformPattern(pattern, m_bytes, m_mask); {
return;
m_size = m_mask.size(); }
#if PATTERNS_USE_HINTS // scan the executable for code
// if there's hints, try those first executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_module);
if (m_module == GetModuleHandle(nullptr))
{ auto matchSuccess = [&](uintptr_t address)
auto range = g_hints.equal_range(m_hash); {
#if PATTERNS_USE_HINTS
if (range.first != range.second) GetHints().emplace(m_hash, address);
{ Citizen_PatternSaveHint(m_hash, address);
std::for_each(range.first, range.second, [&] (const std::pair<uint64_t, uintptr_t>& hint) #else
{ (void)address;
ConsiderMatch(hint.second); #endif
});
return (m_matches.size() == maxCount);
// if the hints succeeded, we don't need to do anything more };
if (!m_matches.empty())
{ const uint8_t* pattern = reinterpret_cast<const uint8_t*>(m_bytes.c_str());
m_matched = true; const char* mask = m_mask.c_str();
return; size_t maskSize = m_mask.size();
} size_t lastWild = m_mask.find_last_of('?');
}
} ptrdiff_t Last[256];
#endif
} std::fill(std::begin(Last), std::end(Last), lastWild == std::string::npos ? -1 : static_cast<ptrdiff_t>(lastWild));
void pattern::EnsureMatches(uint32_t maxCount) for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(maskSize); ++i)
{ {
if (m_matched) if (Last[pattern[i]] < i)
return; {
Last[pattern[i]] = i;
if (!m_rangeStart && !m_rangeEnd && !m_module) }
return; }
// scan the executable for code for (uintptr_t i = executable.begin(), end = executable.end() - maskSize; i <= end;)
executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_module); {
uint8_t* ptr = reinterpret_cast<uint8_t*>(i);
auto matchSuccess = [&] (uintptr_t address) ptrdiff_t j = maskSize - 1;
{
#if PATTERNS_USE_HINTS while ((j >= 0) && (mask[j] == '?' || pattern[j] == ptr[j])) j--;
g_hints.emplace(m_hash, address);
#else if (j < 0)
(void)address; {
#endif m_matches.emplace_back(ptr);
return (m_matches.size() == maxCount); if (matchSuccess(i))
}; {
break;
ptrdiff_t BadCharacter[256]; }
i++;
std::ptrdiff_t index; }
else i += std::max((ptrdiff_t)1, j - Last[ptr[j]]);
const std::uint8_t *pbytes = m_bytes.data(); }
const std::uint8_t *pmask = m_mask.data();
m_matched = true;
for (std::uint32_t bc = 0; bc < 256; ++bc) }
{
for (index = m_size - 1; index >= 0; --index) bool pattern::ConsiderMatch(uintptr_t offset)
{ {
if ((pbytes[index] & pmask[index]) == (bc & pmask[index])) const char* pattern = m_bytes.c_str();
{ const char* mask = m_mask.c_str();
break;
} char* ptr = reinterpret_cast<char*>(offset);
}
for (size_t i = 0, j = m_mask.size(); i < j; i++)
BadCharacter[bc] = index; {
} if (mask[i] == '?')
{
__try continue;
{ }
for (uintptr_t i = executable.begin(), end = executable.end() - m_size; i <= end;)
{ if (pattern[i] != ptr[i])
uint8_t* ptr = reinterpret_cast<uint8_t*>(i); {
return false;
for (index = m_size - 1; index >= 0; --index) }
{ }
if ((pbytes[index] & pmask[index]) != (ptr[index] & pmask[index]))
{ m_matches.emplace_back(ptr);
break;
} return true;
} }
if (index == -1) #if PATTERNS_USE_HINTS
{
m_matches.emplace_back(ptr); void InitializeHints()
{
if (matchSuccess(i)) static std::string modPath;
{
break; if (modPath.empty())
} {
char exeName[512];
i += m_size; GetModuleFileNameA(GetModuleHandle(NULL), exeName, sizeof(exeName));
}
else char* exeBaseName = strrchr(exeName, '\\');
{ exeBaseName[0] = L'\0';
i += max(index - BadCharacter[ptr[index]], 1);
} modPath = exeName;
} modPath += "\\";
}
__except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) GetFullPathNameA(modPath.c_str(), sizeof(exeName), exeName, nullptr);
{ }
m_matched = true; modPath = exeName;
} modPath += "\\";
}
bool pattern::ConsiderMatch(uintptr_t offset)
{ std::string hintsFile = modPath + "hints.dat";
const uint8_t* pattern = m_bytes.data(); FILE* hints = fopen(hintsFile.c_str(), "rb");
const uint8_t* mask = m_mask.data();
if (hints)
char* ptr = reinterpret_cast<char*>(offset); {
while (!feof(hints))
for (size_t i = 0; i < m_size; i++) {
{ uint64_t hash;
if ((pattern[i] & mask[i]) != (ptr[i] & mask[i])) uintptr_t hint;
{
return false; fread(&hash, 1, sizeof(hash), hints);
} fread(&hint, 1, sizeof(hint), hints);
}
hook::pattern::hint(hash, hint);
m_matches.emplace_back(ptr); }
return true; fclose(hints);
} }
}
#if PATTERNS_USE_HINTS
void pattern::hint(uint64_t hash, uintptr_t address)
{
auto range = g_hints.equal_range(hash);
for (auto it = range.first; it != range.second; it++)
{
if (it->second == address)
{
return;
}
}
void pattern::hint(uint64_t hash, uintptr_t address)
g_hints.emplace(hash, address); {
} auto range = GetHints().equal_range(hash);
#endif
} for (auto it = range.first; it != range.second; it++)
{
if (it->second == address)
{
return;
}
}
GetHints().emplace(hash, address);
}
#endif
}

View File

@ -1,242 +1,201 @@
/* /*
* This file is part of the CitizenFX project - http://citizen.re/ * This file is part of the CitizenFX project - http://citizen.re/
* *
* See LICENSE and MENTIONS in the root of the source tree for information * See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing. * regarding licensing.
*/ */
#pragma once #pragma once
#define PATTERNS_USE_HINTS 0 #include <cassert>
#include <vector>
#include <cassert>
#include <vector> #pragma warning(push)
#pragma warning(disable:4201)
namespace hook
{ #define PATTERNS_USE_HINTS 1
extern ptrdiff_t baseAddressDifference;
namespace hook
// sets the base address difference based on an obtained pointer {
inline void set_base(uintptr_t address) class pattern_match
{ {
#ifdef _M_IX86 private:
uintptr_t addressDiff = (address - 0x400000); void* m_pointer;
#elif defined(_M_AMD64)
uintptr_t addressDiff = (address - 0x140000000); public:
#endif inline pattern_match(void* pointer)
: m_pointer(pointer)
// pointer-style cast to ensure unsigned overflow ends up copied directly into a signed value {
baseAddressDifference = *(ptrdiff_t*)&addressDiff; }
}
template<typename T>
// sets the base to the process main base T* get(ptrdiff_t offset = 0) const
void set_base(); {
char* ptr = reinterpret_cast<char*>(m_pointer);
template<typename T> return reinterpret_cast<T*>(ptr + offset);
inline T* getRVA(uintptr_t rva) }
{ };
set_base();
#ifdef _M_IX86 class pattern
return (T*)(baseAddressDifference + 0x400000 + rva); {
#elif defined(_M_AMD64) private:
return (T*)(baseAddressDifference + 0x140000000 + rva); std::string m_bytes;
#endif std::string m_mask;
}
#if PATTERNS_USE_HINTS
class pattern_match uint64_t m_hash;
{ #endif
private:
void* m_pointer; std::vector<pattern_match> m_matches;
public: bool m_matched;
inline pattern_match(void* pointer)
: m_pointer(pointer) union
{ {
} void* m_module;
struct
template<typename T> {
T* get(ptrdiff_t offset = 0) const uintptr_t m_rangeStart;
{ uintptr_t m_rangeEnd;
char* ptr = reinterpret_cast<char*>(m_pointer); };
return reinterpret_cast<T*>(ptr + offset); };
}
}; protected:
inline pattern(void* module)
class pattern : m_rangeStart((uintptr_t)module), m_matched(false), m_rangeEnd(0)
{ {
private: }
std::vector<uint8_t> m_bytes;
std::vector<uint8_t> m_mask; inline pattern(uintptr_t begin, uintptr_t end)
: m_rangeStart(begin), m_rangeEnd(end), m_matched(false)
#if PATTERNS_USE_HINTS {
uint64_t m_hash; }
#endif
void Initialize(const char* pattern, size_t length);
size_t m_size;
private:
std::vector<pattern_match> m_matches; bool ConsiderMatch(uintptr_t offset);
bool m_matched; void EnsureMatches(uint32_t maxCount);
union inline pattern_match _get_internal(size_t index) const
{ {
void* m_module; return m_matches[index];
struct }
{
uintptr_t m_rangeStart; public:
uintptr_t m_rangeEnd; template<size_t Len>
}; pattern(const char(&pattern)[Len])
}; : pattern(GetModuleHandle(NULL))
{
protected: Initialize(pattern, Len);
inline pattern(void* module) }
: m_module(module), m_rangeEnd(0), m_matched(false)
{ inline pattern& count(uint32_t expected) &
} {
EnsureMatches(expected);
inline pattern(uintptr_t begin, uintptr_t end) assert(m_matches.size() == expected);
: m_rangeStart(begin), m_rangeEnd(end), m_matched(false) return *this;
{ }
}
inline pattern& count_hint(uint32_t expected) &
void Initialize(const char* pattern); {
EnsureMatches(expected);
private: return *this;
bool ConsiderMatch(uintptr_t offset); }
void EnsureMatches(uint32_t maxCount); inline pattern& clear() &
{
inline const pattern_match& _get_internal(size_t index) m_matches.clear();
{ m_matched = false;
return m_matches[index]; return *this;
} }
public: inline pattern&& count(uint32_t expected) &&
pattern() {
: m_matched(true) EnsureMatches(expected);
{ assert(m_matches.size() == expected);
} return std::move(*this);
}
pattern(const char *pattern)
: pattern(getRVA<void>(0)) inline pattern&& count_hint(uint32_t expected) &&
{ {
Initialize(pattern); EnsureMatches(expected);
} return std::move(*this);
}
pattern(std::string& pattern)
: pattern(getRVA<void>(0)) inline pattern&& clear() &&
{ {
Initialize(pattern.c_str()); m_matches.clear();
} m_matched = false;
return std::move(*this);
inline pattern& count(uint32_t expected) }
{
EnsureMatches(expected); inline size_t size()
assert(m_matches.size() == expected); {
return *this; EnsureMatches(UINT32_MAX);
} return m_matches.size();
}
inline pattern& count_hint(uint32_t expected)
{ inline bool empty()
EnsureMatches(expected); {
return *this; return size() == 0;
} }
inline pattern& clear(void* module = nullptr) inline pattern_match get(size_t index)
{ {
if (module) EnsureMatches(UINT32_MAX);
m_module = module; return _get_internal(index);
m_matches.clear(); }
m_matched = false;
return *this; inline pattern_match get_one()
} {
return std::forward<pattern>(*this).count(1)._get_internal(0);
inline size_t size() }
{
EnsureMatches(UINT32_MAX); template<typename T = void>
return m_matches.size(); inline auto get_first(ptrdiff_t offset = 0)
} {
return get_one().get<T>(offset);
inline bool empty() }
{
return size() == 0; public:
} #if PATTERNS_USE_HINTS
// define a hint
inline const pattern_match& get(size_t index) static void hint(uint64_t hash, uintptr_t address);
{ #endif
EnsureMatches(UINT32_MAX); };
return _get_internal(index);
} class module_pattern
: public pattern
inline const pattern_match& get_one() {
{ public:
return count(1)._get_internal(0); template<size_t Len>
} module_pattern(void* module, const char(&pattern)[Len])
: pattern(module)
template<typename T = void> {
inline auto get_first(ptrdiff_t offset = 0) Initialize(pattern, Len);
{ }
return get_one().get<T>(offset); };
}
class range_pattern
template <typename Fn> : public pattern
pattern &for_each_result(Fn Pr) {
{ public:
EnsureMatches(UINT32_MAX); template<size_t Len>
range_pattern(uintptr_t begin, uintptr_t end, const char(&pattern)[Len])
for (auto &result : this->m_matches) : pattern(begin, end)
{ {
Pr(result); Initialize(pattern, Len);
} }
};
return *this;
}
template<typename T = void, size_t Len>
public: auto get_pattern(const char(&pattern_string)[Len], ptrdiff_t offset = 0)
#if PATTERNS_USE_HINTS {
// define a hint return pattern(pattern_string).get_first<T>(offset);
static void hint(uint64_t hash, uintptr_t address); }
#endif }
};
#pragma warning(pop)
class module_pattern
: public pattern
{
public:
module_pattern(void* module, const char *pattern)
: pattern(module)
{
Initialize(pattern);
}
module_pattern(void* module, std::string& pattern)
: pattern(module)
{
Initialize(pattern.c_str());
}
};
class range_pattern
: public pattern
{
public:
range_pattern(uintptr_t begin, uintptr_t end, const char *pattern)
: pattern(begin, end)
{
Initialize(pattern);
}
range_pattern(uintptr_t begin, uintptr_t end, std::string& pattern)
: pattern(begin, end)
{
Initialize(pattern.c_str());
}
};
template<typename T = void>
auto get_pattern(const char *pattern_string, ptrdiff_t offset = 0)
{
return pattern(pattern_string).get_first<T>(offset);
}
}

View File

@ -23,8 +23,8 @@ project "iDmacDrv"
filter "platforms:x86" filter "platforms:x86"
targetsuffix "32" targetsuffix "32"
linkoptions { "/DEF:iDmacDrv/src/Source32.def" } linkoptions { "/DEF:$(ProjectDir)/src/Source32.def" }
filter "platforms:x64" filter "platforms:x64"
targetsuffix "64" targetsuffix "64"
linkoptions { "/DEF:iDmacDrv/src/Source64.def" } linkoptions { "/DEF:$(ProjectDir)/src/Source64.def" }

View File

@ -1,2 +1 @@
premake5 vs2017 premake5 vs2019
pause

Binary file not shown.

View File

@ -4,7 +4,7 @@ workspace "OpenParrot"
flags { "StaticRuntime", "No64BitChecks" } flags { "StaticRuntime", "No64BitChecks" }
systemversion "10.0.16299.0" systemversion "latest"
symbols "On" symbols "On"