Raised This Month: $9 Target: $400
 2% 

CSGO correct usage of manual hooks


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
kadet.89
Veteran Member
Join Date: Nov 2012
Old 12-21-2020 , 10:22   CSGO correct usage of manual hooks
Reply With Quote #1

I have a manual hook in my extension declared this way:

PHP Code:
SH_DECL_MANUALHOOK2_void(CPlayer_PlayerRunCmd000CUserCmd*, void*)

CPlayer::CPlayer(CBaseEntityentity)
{
    
SH_ADD_MANUALHOOK(CPlayer_PlayerRunCmdGetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}

CPlayer::~CPlayer(void)
{
    
SH_REMOVE_MANUALHOOK(CPlayer_PlayerRunCmdGetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}

void CPlayer::OnPlayerRunCmd(CUserCmd *cmdvoid *moveHelper)
{
    const 
int pressedButtons GetButtonPressed();
    if(
pressedButtons IN_RELOAD)
    {
        
CBaseEntityactiveWeapon GetActiveWeaponPointer();
        if(!
activeWeapon || strcmp(activeWeapon->GetClassName(), "weapon_knife") != 0)
            
RETURN_META(MRES_IGNORED);

        
CBaseEntityak47 GetWeaponByClassname("weapon_ak47");
        if(!
ak47)
            
RETURN_META(MRES_IGNORED);

        
SH_MCALL(GetBaseEntity(), CPlayer_Weapon_Switch)(ak470);
    }

    
RETURN_META(MRES_IGNORED);

This works, but quite often crashes the server. On in the crashstack I always see the same funtion name and the same stack:

PHP Code:
 0  server.so 0x5d5463
 1  server
.so 0x760f0b
 2  server
.so 0x767b7a
 3  server
.so 0xb8f9e7
 4  sdkhooks
.ext.2.csgo.so 0x1bdfe
 5  server
.so 0x77c1d3
 6  server
.so 0x77c951
 7  server
.so 0x75f47c
 8  server
.so 0xb8c335
 9  extension18
.ext.2.csgo.so 0x35f91
10  server
.so 0x777a94
11  server
.so 0x734db5 
The function where crash begins (extension18.ext.2.csgo.so + 0x35f91) Scroll to the comment (// Crashes here)

PHP Code:
int __cdecl __SourceHook_MFHCls_CPlayer_PlayerRunCmd::Func(int a1int a2int a3)
{
  
int v3// [email protected]
  
int v4// [email protected]
  
int (__cdecl *v5)(intintint); // [email protected]
  
int v6// [email protected]
  
int (__cdecl *v7)(intintint); // [email protected]
  
int v8// [email protected]
  
int v10// [sp+8h] [bp-28h]@1
  
int v11// [sp+Ch] [bp-24h]@1
  
int v12// [sp+10h] [bp-20h]@1
  
void (__cdecl *v13)(intintint); // [sp+14h] [bp-1Ch]@1

  
v12 0;
  
v3 = (*(int (__cdecl **)(intintintintvoid (__cdecl **)(intintint), int *, int *, int *, _DWORD_DWORD))(*(_DWORD *)g_SHPtr 76))(
         
g_SHPtr,
         
__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_HI,
         *(
_DWORD *)(a1 + *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[12])
       + 
* *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[8],
         
a1,
         &
v13,
         &
v12,
         &
v11,
         &
v10,
         
0,
         
0);
  
v11 0;
  
v4 v3;
  while ( 
)
  {
    
v6 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
    if ( !
v6 )
      break;
    
v10 0;
    
v5 = *(int (__cdecl **)(intintint))(*(_DWORD *)v6 8);
    if ( 
v5 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
    {
      
v5 = *(int (__cdecl **)(intintint))(v6 8);
      
v6 = *(_DWORD *)(v6 4) + *(_DWORD *)(v6 12);
      if ( (
unsigned __int8)v5 )
        
v5 = *(int (__cdecl **)(intintint))((char *)v5 + *(_DWORD *)v6 1);
    }
    
v5(v6a2a3);
    
v11 v10;
    if ( 
v10 v12 )
      
v12 v10;
  }
  if ( 
v12 != && (unsigned __int8)(*(int (__cdecl **)(int))(*(_DWORD *)v4 12))(v4) )
  {
    if ( (
unsigned __int8)v13 )
      (*(
void (__cdecl **)(intintint))((char *)v13 + *(_DWORD *)a1 1))(a1a2a3);
    else
      
v13(a1a2a3); // Crashes here
  
}
  
v11 0;
  while ( 
)
  {
    
v8 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
    if ( !
v8 )
      break;
    
v10 0;
    
v7 = *(int (__cdecl **)(intintint))(*(_DWORD *)v8 8);
    if ( 
v7 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
    {
      
v7 = *(int (__cdecl **)(intintint))(v8 8);
      
v8 = *(_DWORD *)(v8 4) + *(_DWORD *)(v8 12);
      if ( (
unsigned __int8)v7 )
        
v7 = *(int (__cdecl **)(intintint))((char *)v7 + *(_DWORD *)v8 1);
    }
    
v7(v8a2a3);
    
v11 v10;
    if ( 
v10 v12 )
      
v12 v10;
  }
  return (*(
int (__cdecl **)(intint))(*(_DWORD *)g_SHPtr 80))(g_SHPtrv4);

Can somebody give me some advice what it could be?
There are some other hooks which I removed from the example: SetTransmit, OnTakeDamage, Weapon_Switch, Weapon_Equip. None of them crashes, but PlayerRunCmd couses crashes in all my extensions. And I don't see any difference.
I thought that it could be not removed CPlayer instance when the CBaseEntity of the attached player stops existing, but the tests show that CPlayer is always deleted before the attached entity is deleted. If I use GameFrame hook instead, then the crashes go away.
kadet.89 is offline
Send a message via Skype™ to kadet.89
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 12-22-2020 , 08:41   Re: CSGO correct usage of manual hooks
Reply With Quote #2

I don't think there is anything wrong with your hook, the crash is quite far down the call stack - based on the stack trace and your code, I'd say the game just isn't liking you calling Weapon_Switch at that time.
__________________
asherkin is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:03.


Powered by vBulletin®
Copyright ©2000 - 2021, vBulletin Solutions, Inc.
Theme made by Freecode