SilentPatch/SilentPatch/Patterns.h

181 lines
3.4 KiB
C
Raw Normal View History

2017-03-06 02:25:46 +05:00
/*
* This file is part of the CitizenFX project - http://citizen.re/
*
* See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing.
*/
#pragma once
#include <cassert>
#include <vector>
2017-09-28 02:17:21 +05:00
#include <string_view>
2017-03-06 02:25:46 +05:00
2017-04-02 22:41:50 +05:00
#pragma warning(push)
#pragma warning(disable:4201)
2017-03-06 02:25:46 +05:00
namespace hook
{
class pattern_match
{
private:
void* m_pointer;
public:
inline pattern_match(void* pointer)
: m_pointer(pointer)
{
}
template<typename T>
T* get(ptrdiff_t offset = 0) const
{
char* ptr = reinterpret_cast<char*>(m_pointer);
return reinterpret_cast<T*>(ptr + offset);
}
};
class pattern
{
private:
2018-02-10 04:50:11 +05:00
std::basic_string<uint8_t> m_bytes;
std::basic_string<uint8_t> m_mask;
2017-03-06 02:25:46 +05:00
#if PATTERNS_USE_HINTS
uint64_t m_hash;
#endif
std::vector<pattern_match> m_matches;
bool m_matched = false;
2017-03-06 02:25:46 +05:00
2018-01-21 17:14:02 +05:00
uintptr_t m_rangeStart;
uintptr_t m_rangeEnd;
2017-03-06 02:25:46 +05:00
private:
2018-04-02 23:11:06 +05:00
static ptrdiff_t get_process_base();
2018-01-21 17:14:02 +05:00
void Initialize(std::string_view pattern);
bool ConsiderHint(uintptr_t offset);
2017-03-06 02:25:46 +05:00
void EnsureMatches(uint32_t maxCount);
2017-04-27 05:18:59 +05:00
inline pattern_match _get_internal(size_t index) const
2017-03-06 02:25:46 +05:00
{
return m_matches[index];
}
2018-01-21 17:14:02 +05:00
inline pattern(uintptr_t module)
: pattern( module, 0 )
{
}
inline pattern(uintptr_t begin, uintptr_t end)
: m_rangeStart(begin), m_rangeEnd(end)
{
}
2017-03-06 02:25:46 +05:00
public:
pattern(std::string_view pattern)
2018-04-02 23:11:06 +05:00
: pattern(get_process_base())
2017-03-06 02:25:46 +05:00
{
Initialize(std::move(pattern));
2017-03-06 02:25:46 +05:00
}
inline pattern(void* module, std::string_view pattern)
2018-01-21 17:14:02 +05:00
: pattern(reinterpret_cast<uintptr_t>(module))
{
Initialize(std::move(pattern));
}
inline pattern(uintptr_t begin, uintptr_t end, std::string_view pattern)
: m_rangeStart(begin), m_rangeEnd(end)
{
Initialize(std::move(pattern));
}
inline pattern&& count(uint32_t expected)
2017-03-06 02:25:46 +05:00
{
EnsureMatches(expected);
assert(m_matches.size() == expected);
return std::forward<pattern>(*this);
2017-03-06 02:25:46 +05:00
}
inline pattern&& count_hint(uint32_t expected)
2017-03-06 02:25:46 +05:00
{
EnsureMatches(expected);
return std::forward<pattern>(*this);
2017-03-06 02:25:46 +05:00
}
inline pattern&& clear()
2017-03-17 04:48:16 +05:00
{
m_matches.clear();
m_matched = false;
return std::forward<pattern>(*this);
2017-04-27 05:18:59 +05:00
}
2017-03-06 02:25:46 +05:00
inline size_t size()
{
EnsureMatches(UINT32_MAX);
return m_matches.size();
}
inline bool empty()
{
return size() == 0;
}
2017-04-27 05:18:59 +05:00
inline pattern_match get(size_t index)
2017-03-06 02:25:46 +05:00
{
EnsureMatches(UINT32_MAX);
return _get_internal(index);
}
2017-04-27 05:18:59 +05:00
inline pattern_match get_one()
2017-03-06 02:25:46 +05:00
{
2017-04-27 05:18:59 +05:00
return std::forward<pattern>(*this).count(1)._get_internal(0);
2017-03-06 02:25:46 +05:00
}
template<typename T = void>
inline auto get_first(ptrdiff_t offset = 0)
{
return get_one().get<T>(offset);
}
2017-05-28 00:44:22 +05:00
template <typename Pred>
inline Pred for_each_result(Pred&& pred)
2017-05-28 00:44:22 +05:00
{
EnsureMatches(UINT32_MAX);
for ( auto it : m_matches )
{
std::forward<Pred>(pred)(it);
2017-05-28 00:44:22 +05:00
}
return std::forward<Pred>(pred);
2017-05-28 00:44:22 +05:00
}
2017-03-06 02:25:46 +05:00
public:
#if PATTERNS_USE_HINTS && PATTERNS_CAN_SERIALIZE_HINTS
2017-03-06 02:25:46 +05:00
// define a hint
static void hint(uint64_t hash, uintptr_t address);
#endif
};
inline pattern make_module_pattern(void* module, std::string_view bytes)
2017-03-06 02:25:46 +05:00
{
return pattern(module, std::move(bytes));
}
2017-03-06 02:25:46 +05:00
inline pattern make_range_pattern(uintptr_t begin, uintptr_t end, std::string_view bytes)
2017-03-17 04:48:16 +05:00
{
return pattern(begin, end, std::move(bytes));
}
2017-03-06 02:25:46 +05:00
template<typename T = void>
inline auto get_pattern(std::string_view pattern_string, ptrdiff_t offset = 0)
2017-03-06 02:25:46 +05:00
{
return pattern(std::move(pattern_string)).get_first<T>(offset);
2017-03-06 02:25:46 +05:00
}
2017-04-02 22:41:50 +05:00
}
#pragma warning(pop)