Use AMTL instead of the stdlib in DynamicHooks
This commit is contained in:
		
							parent
							
								
									8ab9c14e93
								
							
						
					
					
						commit
						c70d3b9ee0
					
				| @ -53,6 +53,12 @@ CHook::CHook(void* pFunc, ICallingConvention* pConvention) | |||||||
| 	m_pRegisters = new CRegisters(pConvention->GetRegisters()); | 	m_pRegisters = new CRegisters(pConvention->GetRegisters()); | ||||||
| 	m_pCallingConvention = pConvention; | 	m_pCallingConvention = pConvention; | ||||||
| 
 | 
 | ||||||
|  | 	if (!m_hookHandler.init()) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if (!m_RetAddr.init()) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
| 	unsigned char* pTarget = (unsigned char *) pFunc; | 	unsigned char* pTarget = (unsigned char *) pFunc; | ||||||
| 
 | 
 | ||||||
| 	// Determine the number of bytes we need to copy
 | 	// Determine the number of bytes we need to copy
 | ||||||
| @ -103,37 +109,56 @@ void CHook::AddCallback(HookType_t eHookType, HookHandlerFn* pCallback) | |||||||
| 	if (!pCallback) | 	if (!pCallback) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (!IsCallbackRegistered(eHookType, pCallback)) | 	HookTypeMap::Insert i = m_hookHandler.findForAdd(eHookType); | ||||||
| 		m_hookHandler[eHookType].push_back(pCallback); | 	if (!i.found()) { | ||||||
|  | 		HookHandlerSet set; | ||||||
|  | 		set.init(); | ||||||
|  | 		m_hookHandler.add(i, eHookType, ke::Move(set)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	i->value.add(pCallback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CHook::RemoveCallback(HookType_t eHookType, HookHandlerFn* pCallback) | void CHook::RemoveCallback(HookType_t eHookType, HookHandlerFn* pCallback) | ||||||
| { | { | ||||||
| 	if (IsCallbackRegistered(eHookType, pCallback)) | 	HookTypeMap::Result r = m_hookHandler.find(eHookType); | ||||||
| 		m_hookHandler[eHookType].remove(pCallback); | 	if (!r.found()) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	r->value.removeIfExists(pCallback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool CHook::IsCallbackRegistered(HookType_t eHookType, HookHandlerFn* pCallback) | bool CHook::IsCallbackRegistered(HookType_t eHookType, HookHandlerFn* pCallback) | ||||||
| { | { | ||||||
| 	std::list<HookHandlerFn *> callbacks = m_hookHandler[eHookType]; | 	HookTypeMap::Result r = m_hookHandler.find(eHookType); | ||||||
| 	for(std::list<HookHandlerFn *>::iterator it=callbacks.begin(); it != callbacks.end(); it++) | 	if (!r.found()) | ||||||
| 	{ | 		return false; | ||||||
| 		if (*it == pCallback) | 
 | ||||||
| 			return true; | 	return r->value.has(pCallback); | ||||||
| 	} |  | ||||||
| 	return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool CHook::AreCallbacksRegistered() | bool CHook::AreCallbacksRegistered() | ||||||
| { | { | ||||||
| 	return !m_hookHandler[HOOKTYPE_PRE].empty() || !m_hookHandler[HOOKTYPE_POST].empty(); | 	HookTypeMap::Result r = m_hookHandler.find(HOOKTYPE_PRE); | ||||||
|  | 	if (r.found() && r->value.elements() > 0) | ||||||
|  | 		return true; | ||||||
|  | 
 | ||||||
|  | 	r = m_hookHandler.find(HOOKTYPE_POST); | ||||||
|  | 	if (r.found() && r->value.elements() > 0) | ||||||
|  | 		return true; | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool CHook::HookHandler(HookType_t eHookType) | bool CHook::HookHandler(HookType_t eHookType) | ||||||
| { | { | ||||||
| 	bool bOverride = false; | 	bool bOverride = false; | ||||||
| 	std::list<HookHandlerFn *> callbacks = this->m_hookHandler[eHookType]; | 	HookTypeMap::Result r = m_hookHandler.find(eHookType); | ||||||
| 	for(std::list<HookHandlerFn *>::iterator it=callbacks.begin(); it != callbacks.end(); it++) | 	if (!r.found()) | ||||||
|  | 		return bOverride; | ||||||
|  | 
 | ||||||
|  | 	HookHandlerSet &callbacks = r->value; | ||||||
|  | 	for(HookHandlerSet::iterator it=callbacks.iter(); !it.empty(); it.next()) | ||||||
| 	{ | 	{ | ||||||
| 		bool result = ((HookHandlerFn) *it)(eHookType, this); | 		bool result = ((HookHandlerFn) *it)(eHookType, this); | ||||||
| 		if (result) | 		if (result) | ||||||
| @ -144,15 +169,17 @@ bool CHook::HookHandler(HookType_t eHookType) | |||||||
| 
 | 
 | ||||||
| void* __cdecl CHook::GetReturnAddress(void* pESP) | void* __cdecl CHook::GetReturnAddress(void* pESP) | ||||||
| { | { | ||||||
| 	if (m_RetAddr.count(pESP) == 0) | 	ReturnAddressMap::Result r = m_RetAddr.find(pESP); | ||||||
|  | 	if (!r.found()) | ||||||
| 		puts("ESP not present."); | 		puts("ESP not present."); | ||||||
| 
 | 
 | ||||||
| 	return m_RetAddr[pESP]; | 	return r->value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void __cdecl CHook::SetReturnAddress(void* pRetAddr, void* pESP) | void __cdecl CHook::SetReturnAddress(void* pRetAddr, void* pESP) | ||||||
| { | { | ||||||
| 	m_RetAddr[pESP] = pRetAddr; | 	ReturnAddressMap::Insert i = m_RetAddr.findForAdd(pESP); | ||||||
|  | 	m_RetAddr.add(i, pESP, pRetAddr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void* CHook::CreateBridge() | void* CHook::CreateBridge() | ||||||
|  | |||||||
| @ -34,11 +34,10 @@ | |||||||
| // ============================================================================
 | // ============================================================================
 | ||||||
| // >> INCLUDES
 | // >> INCLUDES
 | ||||||
| // ============================================================================
 | // ============================================================================
 | ||||||
| #include <list> |  | ||||||
| #include <map> |  | ||||||
| 
 |  | ||||||
| #include "registers.h" | #include "registers.h" | ||||||
| #include "convention.h" | #include "convention.h" | ||||||
|  | #include <am-hashmap.h> | ||||||
|  | #include <am-hashset.h> | ||||||
| 
 | 
 | ||||||
| // ============================================================================
 | // ============================================================================
 | ||||||
| // >> HookType_t
 | // >> HookType_t
 | ||||||
| @ -63,6 +62,20 @@ typedef bool (*HookHandlerFn)(HookType_t, CHook*); | |||||||
| #define __cdecl | #define __cdecl | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | struct IntegerPolicy | ||||||
|  | { | ||||||
|  | 	static inline uint32_t hash(size_t i) { | ||||||
|  | 		return ke::HashInteger<sizeof(size_t)>(i); | ||||||
|  | 	} | ||||||
|  | 	static inline bool matches(size_t i1, size_t i2) { | ||||||
|  | 		return i1 == i2; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef ke::HashSet<HookHandlerFn*, ke::PointerPolicy<HookHandlerFn>> HookHandlerSet; | ||||||
|  | typedef ke::HashMap<HookType_t, HookHandlerSet, IntegerPolicy> HookTypeMap; | ||||||
|  | typedef ke::HashMap<void*, void*, ke::PointerPolicy<void>> ReturnAddressMap; | ||||||
|  | 
 | ||||||
| namespace sp | namespace sp | ||||||
| { | { | ||||||
| 	class MacroAssembler; | 	class MacroAssembler; | ||||||
| @ -164,12 +177,12 @@ private: | |||||||
| 	void __cdecl SetReturnAddress(void* pRetAddr, void* pESP); | 	void __cdecl SetReturnAddress(void* pRetAddr, void* pESP); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	std::map<HookType_t, std::list<HookHandlerFn*> > m_hookHandler; | 
 | ||||||
|  | 	HookTypeMap m_hookHandler; | ||||||
| 
 | 
 | ||||||
| 	// Address of the original function
 | 	// Address of the original function
 | ||||||
| 	void* m_pFunc; | 	void* m_pFunc; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	ICallingConvention* m_pCallingConvention; | 	ICallingConvention* m_pCallingConvention; | ||||||
| 
 | 
 | ||||||
| 	// Address of the bridge
 | 	// Address of the bridge
 | ||||||
| @ -184,7 +197,7 @@ public: | |||||||
| 	// New return address
 | 	// New return address
 | ||||||
| 	void* m_pNewRetAddr; | 	void* m_pNewRetAddr; | ||||||
| 
 | 
 | ||||||
| 	std::map<void*, void*> m_RetAddr; | 	ReturnAddressMap m_RetAddr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif // _HOOK_H
 | #endif // _HOOK_H
 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user