2019-03-21 20:18:31 +01:00
# include "common.hpp"
# include "detour_hook.hpp"
# include "logger.hpp"
# include "memory/handle.hpp"
2020-02-22 18:37:42 -05:00
# include <..\MinHook\include\MinHook.h>
2019-03-21 20:18:31 +01:00
namespace big
{
2020-02-22 18:37:42 -05:00
detour_hook : : detour_hook ( std : : string name , void * target , void * detour ) :
2019-03-21 20:18:31 +01:00
m_name ( std : : move ( name ) ) ,
m_target ( target ) ,
m_detour ( detour )
{
fix_hook_address ( ) ;
if ( auto status = MH_CreateHook ( m_target , m_detour , & m_original ) ; status = = MH_OK )
{
2020-02-22 18:37:42 -05:00
LOG ( INFO_TO_FILE ) < < " Created hook ' " < < m_name < < " '. " ;
2019-03-21 20:18:31 +01:00
}
else
{
throw std : : runtime_error ( fmt : : format ( " Failed to create hook '{}' at 0x{:X} (error: {}) " , m_name , reinterpret_cast < std : : uintptr_t > ( m_target ) , MH_StatusToString ( status ) ) ) ;
}
}
detour_hook : : ~ detour_hook ( ) noexcept
{
if ( m_target )
{
MH_RemoveHook ( m_target ) ;
}
2020-02-22 18:37:42 -05:00
LOG ( INFO ) < < " Removed hook ' " < < m_name < < " '. " ;
2019-03-21 20:18:31 +01:00
}
void detour_hook : : enable ( )
{
if ( auto status = MH_EnableHook ( m_target ) ; status = = MH_OK )
{
2020-02-22 18:37:42 -05:00
LOG ( INFO_TO_FILE ) < < " Enabled hook ' " < < m_name < < " '. " ;
2019-03-21 20:18:31 +01:00
}
else
{
throw std : : runtime_error ( fmt : : format ( " Failed to enable hook 0x{:X} ({}) " , reinterpret_cast < std : : uintptr_t > ( m_target ) , MH_StatusToString ( status ) ) ) ;
}
}
void detour_hook : : disable ( )
{
if ( auto status = MH_DisableHook ( m_target ) ; status = = MH_OK )
{
2020-02-22 18:37:42 -05:00
LOG ( INFO_TO_FILE ) < < " Disabled hook ' " < < m_name < < " '. " ;
2019-03-21 20:18:31 +01:00
}
else
{
2020-02-22 18:37:42 -05:00
LOG ( WARNING ) < < " Failed to disable hook ' " < < m_name < < " '. " ;
2019-03-21 20:18:31 +01:00
}
}
2020-02-22 18:37:42 -05:00
DWORD exp_handler ( PEXCEPTION_POINTERS exp , std : : string const & name )
2019-03-21 20:18:31 +01:00
{
return exp - > ExceptionRecord - > ExceptionCode = = STATUS_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH ;
}
void detour_hook : : fix_hook_address ( )
{
__try
{
auto ptr = memory : : handle ( m_target ) ;
while ( ptr . as < std : : uint8_t & > ( ) = = 0xE9 )
{
ptr = ptr . add ( 1 ) . rip ( ) ;
}
m_target = ptr . as < void * > ( ) ;
}
__except ( exp_handler ( GetExceptionInformation ( ) , m_name ) )
{
[ this ] ( )
{
throw std : : runtime_error ( fmt : : format ( " Failed to fix hook address for '{}' " , m_name ) ) ;
} ( ) ;
}
}
}