All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2618 lines
57 KiB
C++
2618 lines
57 KiB
C++
// ACHooks.cpp : Implementation of CDecalApp and DLL registration.
|
|
|
|
#include "stdafx.h"
|
|
#include "ACHooks.h"
|
|
#include <math.h>
|
|
#include <time.h> /* Heyus 23 March 2003 */
|
|
#include ".\achooks.h"
|
|
|
|
/*
|
|
I believe in VC6, the limit of unnamed variables (_bstr_t("foo")) has been reached,
|
|
which caused the following error:
|
|
F:\Decal\source\Decal\ACHooks.cpp(467) : fatal error C1001: INTERNAL COMPILER ERROR
|
|
(compiler file 'E:\8168\vc98\p2\src\P2\main.c', line 494)
|
|
Please choose the Technical Support command on the Visual C++
|
|
Help menu, or open the Technical Support help file for more information
|
|
This macro allows us to use a single variable, while keeping more or less the same syntax.
|
|
A variable of type _bstr_t named _Unnamed must be declared in any procedure this is used.
|
|
|
|
Note - This only works with inline strings -> L"Foo"
|
|
*/
|
|
#define BSTRT(x) (_Unnamed = L##x, _Unnamed)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
cACHooks* cACHooks::s_pACHooks = NULL;
|
|
long g_lObjectDestroyedProc = 0;
|
|
long g_lSelectItemHijackProc = 0;
|
|
long g_lIdentifyHijackProc = 0;
|
|
long g_lToolTextProc = 0;
|
|
long g_lToolText2Proc = 0;
|
|
|
|
void (__fastcall *pfnOldChatMessage)(int _ecx, int _edx, char *, DWORD ) = NULL;
|
|
void (*pfnOldChatText)() = NULL;
|
|
void (*pfnUseItem)( DWORD, DWORD ) = NULL;
|
|
void (*pfnMoveItemEx)( DWORD, DWORD, DWORD ) = NULL;
|
|
void ( __fastcall *pfnInternalStringDestructor)( qString * ) = NULL;
|
|
long (*pfnSendMessageToID)( qString *, long ) = NULL;
|
|
long (*pfnSendMessageToName)( qString *, qString * ) = NULL;
|
|
long (*pfnSendMessageByMask)( long, qString * ) = NULL;
|
|
long (*pfnLocalChatText)( qString * ) = NULL;
|
|
long (*pfnLocalChatEmote)( qString * ) = NULL;
|
|
qString* ( __fastcall *pfnInternalStringConstructor)( qString *, long, char * ) = NULL;
|
|
|
|
bool g_bTimestamp;
|
|
char *g_szTimestampFormat;
|
|
DWORD g_lTimestampColor;
|
|
char g_charBufferPreviousCall;
|
|
|
|
extern void __fastcall OnChatMessage( int _ecx, int _edx, char* pText, long dwColor );
|
|
extern void CatchToolText();
|
|
extern void CatchToolTextAppend();
|
|
extern void OnChatText();
|
|
|
|
extern void IdentifyShortcircuit();
|
|
extern void SelectItemHook();
|
|
extern void ObjectDestroyedHook();
|
|
extern DWORD HookCall (DWORD dwCallAddress, DWORD dwReplacement);
|
|
|
|
cACHooks::cACHooks()
|
|
{
|
|
g_bTimestamp = false;
|
|
s_pACHooks = this;
|
|
m_bDecalRef = false;
|
|
m_bIdQueueRef = false;
|
|
m_bMismatch = true;
|
|
m_bPrevSelect = false;
|
|
m_bCurrentSelect = false;
|
|
m_bMouse = false;
|
|
m_bCastSpell = false;
|
|
m_bMoveItem = false;
|
|
m_bSelectItem = false;
|
|
m_bUseItem = false;
|
|
m_bAllYourBase = false;
|
|
m_bSetCombatState = false;
|
|
m_bCombatStateOffset = false;
|
|
m_bChatState = false;
|
|
m_bRequestID = false;
|
|
m_bStackCount = false;
|
|
m_bTestFormula = false;
|
|
m_bVendorID = false;
|
|
m_bBusyState = false;
|
|
m_bPointerState = false;
|
|
m_bMoveItemEx = false;
|
|
m_bFaceHeading = false;
|
|
m_bChatMessageAddy = false;
|
|
m_bSendMessageToID = false;
|
|
m_bSendMessageToName = false;
|
|
m_bSendMessageToMask = false;
|
|
m_bLocalChatText = false;
|
|
m_bLocalChatEmote = false;
|
|
m_bSetAutorun = false;
|
|
m_bGetVital = false;
|
|
m_bGetAttribute = false;
|
|
m_bGetSkill = false;
|
|
m_bLogout = false;
|
|
m_bSecureTrade_Add = false;
|
|
m_bSecureTrade_Add_Off1 = false;
|
|
m_bSecureTrade_Add_Off2 = false;
|
|
m_bGetSkillInfo = false;
|
|
m_bGetAttributeInfo = false;
|
|
m_bGetVitalInfo = false;
|
|
m_bSelectItemHook = false;
|
|
m_bUstAddItem_Useable = false;
|
|
m_bRequestShortcircuit = false;
|
|
m_bToolTextHook = false;
|
|
m_bToolText2Hook = false;
|
|
m_bIdleLoc = false;
|
|
|
|
m_Hooks = 0;
|
|
memset(m_HooksEx, 0, sizeof(m_HooksEx));
|
|
m_HookCount = 0;
|
|
|
|
|
|
USES_CONVERSION;
|
|
_bstr_t _Unnamed;
|
|
|
|
|
|
char szPath[ MAX_PATH ];
|
|
DWORD dwCount = MAX_PATH;
|
|
|
|
|
|
g_charBufferPreviousCall = '\n';
|
|
DWORD dwTimestamp = 0;
|
|
char szTimestampFormat[ MAX_PATH ];
|
|
DWORD lTimestampFormatLength = MAX_PATH;
|
|
|
|
RegKey key;
|
|
if( key.Open( HKEY_LOCAL_MACHINE, "SOFTWARE\\Decal", KEY_READ ) == ERROR_SUCCESS )
|
|
{
|
|
if( key.QueryDWORDValue( _T("Timestamp"), dwTimestamp ) != ERROR_SUCCESS )
|
|
dwTimestamp = 0;
|
|
|
|
if( key.QueryStringValue( _T("TimestampFormat"), szTimestampFormat, &lTimestampFormatLength ) != ERROR_SUCCESS ) /* Heyus 21 March 2003 */
|
|
memset( szTimestampFormat, 0, sizeof(szTimestampFormat) ), strncpy( szTimestampFormat, "[%H:%M]", sizeof( szTimestampFormat ) );
|
|
|
|
if( key.QueryDWORDValue( _T("TimestampColor"), g_lTimestampColor ) != ERROR_SUCCESS )
|
|
g_lTimestampColor = 12; // Grey
|
|
|
|
key.Close();
|
|
}
|
|
|
|
int iStrLen = strlen( szTimestampFormat ) + 2;
|
|
g_szTimestampFormat = new char[ iStrLen ];
|
|
memset( g_szTimestampFormat, 0, iStrLen );
|
|
_snprintf( g_szTimestampFormat, iStrLen, "%s ", szTimestampFormat );
|
|
|
|
// 0xFFFFFFFF = same color as chat text, for those that want time stamps but don't
|
|
// want to infringe upon their 300 max chat window items
|
|
|
|
if( g_lTimestampColor < 0 || g_lTimestampColor > 22 && g_lTimestampColor != 0xFFFFFFFF )
|
|
g_lTimestampColor = 12; // Grey
|
|
|
|
g_bTimestamp = dwTimestamp ? true : false ;
|
|
|
|
|
|
|
|
|
|
TCHAR szFilename[ MAX_PATH ];
|
|
::GetModuleFileName( NULL, szFilename, MAX_PATH );
|
|
LPTSTR strProcessName = ::_tcsrchr( szFilename, _T( '\\' ) );
|
|
|
|
strProcessName[ 7 ] = _T( '\0' );
|
|
|
|
if( ::_tcsicmp( strProcessName + 1, _T( "client" ) ) != 0 )
|
|
return;
|
|
|
|
|
|
|
|
|
|
key.Open( HKEY_LOCAL_MACHINE, "SOFTWARE\\Decal\\Agent", KEY_READ );
|
|
key.QueryStringValue( _T("AgentPath"), szPath, &dwCount );
|
|
|
|
strncat( szPath, "\\memlocs.xml", MAX_PATH );
|
|
|
|
MSXML::IXMLDOMDocumentPtr pMemLocDoc;
|
|
|
|
pMemLocDoc.CreateInstance( __uuidof( MSXML::DOMDocument ) );
|
|
pMemLocDoc->async = false;
|
|
|
|
VARIANT_BOOL bSuccess = pMemLocDoc->load( szPath );
|
|
if( ! bSuccess )
|
|
{
|
|
std::string szXML;
|
|
DecryptXML( szPath, szXML );
|
|
|
|
if( szXML != "" )
|
|
bSuccess = pMemLocDoc->loadXML( _bstr_t( szXML.c_str() ) );
|
|
}
|
|
|
|
if( bSuccess )
|
|
{
|
|
MSXML::IXMLDOMElementPtr pNode = pMemLocDoc->selectSingleNode( BSTRT( "locations" ) );
|
|
|
|
long lVerMajor = 0, lVerMinor = 0, lVerRelease = 0;
|
|
_variant_t vVersion = pNode->getAttribute( BSTRT( "version" ) );
|
|
|
|
char *szTemp, *szVersion = OLE2A( vVersion.bstrVal );
|
|
|
|
// I'm tired and sscanf is crashing - this works even if it's lame
|
|
lVerMajor = atol( szVersion );
|
|
szTemp = strstr( szVersion, "." ) + 1;
|
|
lVerMinor = atol( szTemp );
|
|
szTemp = strstr( szTemp, "." ) + 1;
|
|
lVerRelease = atol( szTemp );
|
|
|
|
RegKey rk;
|
|
if( rk.Open( HKEY_LOCAL_MACHINE, _T( "Software\\Microsoft\\Microsoft Games\\Asheron's Call\\1.00" ) ) == ERROR_SUCCESS )
|
|
{
|
|
TCHAR szClientPath[ MAX_PATH ];
|
|
DWORD dwPathLength = MAX_PATH;
|
|
if( rk.QueryStringValue ( _T( "path" ), szClientPath, &dwPathLength ) == ERROR_SUCCESS )
|
|
{
|
|
::_tcscpy( szClientPath + ( dwPathLength - 1 ), _T( "\\client.exe" ) );
|
|
|
|
DWORD dwDummy,
|
|
dwVerSize = ::GetFileVersionInfoSize( const_cast< LPTSTR > ( szClientPath ), &dwDummy );
|
|
if( dwVerSize != 0 )
|
|
{
|
|
BYTE *pbVersionInfo = reinterpret_cast< BYTE * >( ::_alloca( dwVerSize ) );
|
|
|
|
::GetFileVersionInfo( const_cast< LPTSTR > ( szClientPath ), 0, dwVerSize, pbVersionInfo );
|
|
|
|
VS_FIXEDFILEINFO *vffi;
|
|
UINT nLength = sizeof( VS_FIXEDFILEINFO );
|
|
if( ::VerQueryValue( pbVersionInfo, _T( "\\" ), reinterpret_cast< LPVOID * >( &vffi ), &nLength ) )
|
|
{
|
|
if( (static_cast< long >( HIWORD( vffi->dwFileVersionMS ) ) == lVerMajor) &&
|
|
(static_cast< long >( LOWORD( vffi->dwFileVersionMS ) ) == lVerMinor) &&
|
|
(static_cast< long >( HIWORD( vffi->dwFileVersionLS ) ) == lVerRelease) )
|
|
{
|
|
m_bMismatch = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MSXML::IXMLDOMNodeListPtr pNodes = pMemLocDoc->selectNodes( BSTRT( "/locations/memloc" ) );
|
|
|
|
for( pNode = pNodes->nextNode(); pNode.GetInterfacePtr() != NULL; pNode = pNodes->nextNode() )
|
|
{
|
|
_variant_t vName = pNode->getAttribute( _T( "name" ) ), vValue = pNode->getAttribute( _T( "value" ) );
|
|
|
|
sMemoryLocation loc;
|
|
|
|
loc.Name = OLE2A( vName.bstrVal );
|
|
loc.Location = wcstoul( vValue.bstrVal, 0, 16 );
|
|
|
|
m_mLocationList[ loc.Name ] = loc;
|
|
}
|
|
}
|
|
|
|
long Val;
|
|
if( QueryMemLoc( BSTRT( "PrevItem1" ), &Val ) == S_OK )
|
|
m_lPrevSelect[0] = Val;
|
|
if( QueryMemLoc( BSTRT( "PrevItem2" ), &Val ) == S_OK )
|
|
{
|
|
m_lPrevSelect[1] = Val;
|
|
m_bPrevSelect = true;
|
|
m_Hooks |= ePrevSelect ;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "CurrentItem1" ), &Val ) == S_OK )
|
|
m_lCurrentSelect[0] = Val;
|
|
if( QueryMemLoc( BSTRT( "CurrentItem2" ), &Val ) == S_OK )
|
|
{
|
|
m_lCurrentSelect[1] = Val;
|
|
m_bCurrentSelect = true;
|
|
m_Hooks |= eCurrentSelect ;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ChatMessage" ), &Val ) == S_OK )
|
|
pfnOldChatMessage = reinterpret_cast< void (__fastcall*)( int, int, char *, DWORD ) >( Val );
|
|
if( QueryMemLoc( BSTRT( "ChatMessageAddy" ), &Val ) == S_OK )
|
|
{
|
|
m_lChatMessageAddy = Val;
|
|
m_bChatMessageAddy = true;
|
|
}
|
|
if( QueryMemLoc( BSTRT( "ChatText" ), &Val ) == S_OK )
|
|
pfnOldChatText = reinterpret_cast< void (*)() >( Val );
|
|
|
|
|
|
if( QueryMemLoc( BSTRT( "Mouse1X" ), &Val ) == S_OK )
|
|
m_lMouse[0] = Val;
|
|
if( QueryMemLoc( BSTRT( "Mouse2X" ), &Val ) == S_OK )
|
|
m_lMouse[1] = Val;
|
|
if( QueryMemLoc( BSTRT( "Mouse3X" ), &Val ) == S_OK )
|
|
m_lMouse[2] = Val;
|
|
if( QueryMemLoc( BSTRT( "Mouse4X" ), &Val ) == S_OK )
|
|
{
|
|
m_bMouse = true;
|
|
m_lMouse[3] = Val;
|
|
m_Hooks |= eMouse ;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "CastSpell" ), &Val ) == S_OK )
|
|
{
|
|
m_bCastSpell = true;
|
|
m_Hooks |= eCastSpell ;
|
|
m_lCastSpell = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "MoveItem" ), &Val ) == S_OK )
|
|
{
|
|
m_bMoveItem = true;
|
|
m_Hooks |= eMoveItem ;
|
|
m_lMoveItem = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SelectItem" ), &Val ) == S_OK )
|
|
{
|
|
m_bSelectItem = true;
|
|
m_Hooks |= eSelectItem ;
|
|
m_lSelectItem = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "UseItem" ), &Val ) == S_OK )
|
|
{
|
|
m_bUseItem = true;
|
|
m_Hooks |= eUseItem ;
|
|
SetHookEx( eUseItemRaw );
|
|
SetHookEx( eUseFociSpell );
|
|
m_lUseItem = Val;
|
|
pfnUseItem = reinterpret_cast< void (*)( DWORD, DWORD ) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "AllYourBase" ), &Val ) == S_OK )
|
|
{
|
|
// The memloc formerly known as CombatState
|
|
m_bAllYourBase = true;
|
|
m_Hooks |= eCombatState ;
|
|
m_lAllYourBase = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SetCombatState" ), &Val ) == S_OK )
|
|
{
|
|
m_bSetCombatState = true;
|
|
m_Hooks |= eSetCombatState ;
|
|
m_lSetCombatState = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "CombatStateOffset" ), &Val ) == S_OK )
|
|
{
|
|
m_bCombatStateOffset = true;
|
|
m_Hooks |= eCombatState ;
|
|
m_lCombatStateOffset = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ChatState" ), &Val ) == S_OK )
|
|
{
|
|
m_bChatState = true;
|
|
m_Hooks |= eChatState ;
|
|
m_lChatState = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "GetFellowStats" ), &Val ) == S_OK )
|
|
{
|
|
m_bRequestID = true;
|
|
m_lRequestID = Val;
|
|
m_Hooks |= eGetFellowStats;
|
|
SetHookEx( eRequestID );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "RequestID" ), &Val ) == S_OK )
|
|
{
|
|
m_bRequestID = true;
|
|
m_lRequestID = Val;
|
|
m_Hooks |= eGetFellowStats;
|
|
SetHookEx( eRequestID );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "NumStackItemsSelected" ), &Val ) == S_OK )
|
|
{
|
|
m_bStackCount = true;
|
|
m_Hooks |= eStackCount ;
|
|
m_lStackCount = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "TestFormula" ), &Val ) == S_OK )
|
|
m_lTestFormula = Val;
|
|
if( QueryMemLoc( BSTRT( "TestFormulavtp" ), &Val ) == S_OK )
|
|
{
|
|
m_bTestFormula = true;
|
|
m_Hooks |= eTestFormula ;
|
|
m_lTestFormulaVTable = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "VendorID" ), &Val ) == S_OK )
|
|
{
|
|
m_bVendorID = true;
|
|
m_Hooks |= eVendorID ;
|
|
m_lVendorID = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ItemBusyState" ), &Val ) == S_OK )
|
|
{
|
|
m_bBusyState = true;
|
|
m_Hooks |= eBusyState ;
|
|
m_lBusyState = Val;
|
|
}
|
|
if( QueryMemLoc( BSTRT( "ItemBusyGUID" ), &Val ) == S_OK )
|
|
{
|
|
m_bBusyStateID = true;
|
|
m_Hooks |= eBusyStateID ;
|
|
m_lBusyStateID = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "PointerState" ), &Val ) == S_OK )
|
|
{
|
|
m_bPointerState = true;
|
|
m_Hooks |= ePointerState ;
|
|
m_lPointerState = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "MoveItemEx" ), &Val ) == S_OK )
|
|
{
|
|
m_bMoveItemEx = true;
|
|
m_Hooks |= eMoveItemEx ;
|
|
m_lMoveItemEx = Val;
|
|
pfnMoveItemEx = reinterpret_cast< void (*)(DWORD, DWORD, DWORD) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "3DAreaWidth" ), &Val ) == S_OK )
|
|
{
|
|
m_bArea3DWidth = true;
|
|
m_Hooks |= eArea3DWidth ;
|
|
m_lpArea3DWidth = reinterpret_cast< long * >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "3DAreaHeight" ), &Val ) == S_OK )
|
|
{
|
|
m_bArea3DHeight = true;
|
|
m_Hooks |= eArea3DHeight ;
|
|
m_lpArea3DHeight = reinterpret_cast< long * >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ObjectFromGUID" ), &Val ) == S_OK ) {
|
|
m_lObjectFromGuid = Val;
|
|
SetHookEx( eObjectFromGUID );
|
|
if( QueryMemLoc( BSTRT( "ObjectFromGUIDClass" ), &Val ) == S_OK )
|
|
{
|
|
m_lObjectFromGuidClass = Val;
|
|
SetHookEx( eObjectFromGUIDClass );
|
|
m_bObjectFromGuid = true;
|
|
}
|
|
}
|
|
m_lMovementThingyParent = m_lMovementThingyOffset = m_lFaceHeading = 0;
|
|
|
|
if( QueryMemLoc( BSTRT( "MovementThingyParent" ), &Val ) == S_OK)
|
|
{
|
|
m_lMovementThingyParent = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "MovementThingyOffset" ), &Val ) == S_OK)
|
|
{
|
|
m_lMovementThingyOffset = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "FaceHeading" ), &Val ) == S_OK)
|
|
{
|
|
m_lFaceHeading = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SetAutorun" ), &Val ) == S_OK)
|
|
{
|
|
m_lSetAutorun = Val;
|
|
}
|
|
|
|
if (m_lMovementThingyParent && m_lMovementThingyOffset && m_lFaceHeading)
|
|
{
|
|
m_bFaceHeading = true;
|
|
|
|
m_Hooks |= eFaceHeading;
|
|
}
|
|
|
|
if (m_lMovementThingyParent && m_lMovementThingyOffset && m_lSetAutorun)
|
|
{
|
|
m_bSetAutorun = true;
|
|
|
|
m_Hooks |= eSetAutorun;
|
|
}
|
|
|
|
/*
|
|
// While the address of ObjectDestroyed is interesting, it isn't actually needed.
|
|
// We can't assume that the calls we're hooking call to this address, as they
|
|
// might have already been hooked!
|
|
if( QueryMemLoc( BSTRT( "ObjectDestroyed"), &Val ) == S_OK )
|
|
{
|
|
}
|
|
*/
|
|
|
|
long lCall1 = 0, lCall2 = 0;
|
|
if( QueryMemLoc( BSTRT( "ObjectDestroyed_Call1"), &Val ) == S_OK )
|
|
{
|
|
lCall1 = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ObjectDestroyed_Call2"), &Val ) == S_OK )
|
|
{
|
|
lCall2 = Val;
|
|
}
|
|
|
|
if (lCall1 && lCall2)
|
|
{
|
|
DWORD dwFunc1 = HookCall (lCall1, (DWORD) ObjectDestroyedHook);
|
|
DWORD dwFunc2 = HookCall (lCall2, (DWORD) ObjectDestroyedHook);
|
|
|
|
_ASSERTE (dwFunc1 && (dwFunc1 == dwFunc2));
|
|
|
|
if (dwFunc1 && (dwFunc1 != dwFunc2))
|
|
{
|
|
// Doh, okay put them back, something's wrong.
|
|
HookCall (lCall1, dwFunc1);
|
|
HookCall (lCall2, dwFunc2);
|
|
}
|
|
else
|
|
{
|
|
m_Hooks |= eObjectDestroyed;
|
|
g_lObjectDestroyedProc = dwFunc1;
|
|
}
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "InternalStringConstructor" ), &Val ) == S_OK)
|
|
{
|
|
m_bInternalStringConstructor = true;
|
|
m_lInternalStringConstructor = Val;
|
|
|
|
pfnInternalStringConstructor = reinterpret_cast< qString *(__fastcall*)(qString *, long, char *) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "InternalStringDestructor" ), &Val ) == S_OK)
|
|
{
|
|
m_bInternalStringDestructor = true;
|
|
m_lInternalStringDestructor = Val;
|
|
|
|
pfnInternalStringDestructor = reinterpret_cast< void(__fastcall *)(qString *) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SendMessageToID" ), &Val ) == S_OK)
|
|
{
|
|
m_bSendMessageToID = true;
|
|
m_lSendMessageToID = Val;
|
|
|
|
pfnSendMessageToID = reinterpret_cast< long(*)(qString *, long) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SendMessageToName" ), &Val ) == S_OK)
|
|
{
|
|
m_bSendMessageToName = true;
|
|
m_lSendMessageToName = Val;
|
|
|
|
pfnSendMessageToName = reinterpret_cast< long(*)(qString *, qString *) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SendMessageToMask" ), &Val ) == S_OK)
|
|
{
|
|
m_bSendMessageToMask = true;
|
|
m_lSendMessageToMask = Val;
|
|
|
|
pfnSendMessageByMask = reinterpret_cast< long(*)( long, qString * ) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "LocalChatText" ), &Val ) == S_OK)
|
|
{
|
|
m_bLocalChatText = true;
|
|
m_lLocalChatText = Val;
|
|
|
|
pfnLocalChatText = reinterpret_cast< long(*)(qString *) >( Val );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "LocalChatEmote" ), &Val ) == S_OK)
|
|
{
|
|
m_bLocalChatEmote = true;
|
|
m_lLocalChatEmote = Val;
|
|
|
|
pfnLocalChatEmote = reinterpret_cast< long(*)(qString *) >( Val );
|
|
}
|
|
|
|
if( m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToID )
|
|
m_Hooks |= eSendTell;
|
|
|
|
if( m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToName )
|
|
m_Hooks |= eSendTellEx;
|
|
|
|
if( m_bInternalStringConstructor && m_bInternalStringDestructor && m_bLocalChatText )
|
|
m_Hooks |= eLocalChatText;
|
|
|
|
if( m_bInternalStringConstructor && m_bInternalStringDestructor && m_bLocalChatEmote )
|
|
m_Hooks |= eLocalChatEmote;
|
|
|
|
if( m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToMask )
|
|
SetHookEx( eSendMessageByMask );
|
|
|
|
if( QueryMemLoc( BSTRT( "VitalBase" ), &Val ) == S_OK )
|
|
{
|
|
m_lVitalBase = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "GetVital" ), &Val ) == S_OK )
|
|
{
|
|
m_lGetVital = Val;
|
|
m_bGetVital = true;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "GetAttribute" ), &Val ) == S_OK )
|
|
{
|
|
m_lGetAttribute = Val;
|
|
m_bGetAttribute = true;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "GetSkill" ), &Val ) == S_OK )
|
|
{
|
|
m_lGetSkill = Val;
|
|
m_bGetSkill = true;
|
|
}
|
|
|
|
if( m_lVitalBase )
|
|
{
|
|
if( m_bGetVital )
|
|
m_Hooks |= eGetVital;
|
|
|
|
if( m_bGetAttribute )
|
|
m_Hooks |= eGetAttribute;
|
|
|
|
if( m_bGetSkill )
|
|
m_Hooks |= eGetSkill;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "Logout" ), &Val ) == S_OK )
|
|
{
|
|
m_lLogout = Val;
|
|
m_bLogout = true;
|
|
SetHookEx(eLogout);
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "SecureTrade_Add" ), &Val) == S_OK)
|
|
{
|
|
m_lSecureTrade_Add = Val;
|
|
m_bSecureTrade_Add = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "SecureTrade_Add_Off1" ), &Val) == S_OK)
|
|
{
|
|
m_lSecureTrade_Add_Off1 = Val;
|
|
m_bSecureTrade_Add_Off1 = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "SecureTrade_Add_Off2" ), &Val) == S_OK)
|
|
{
|
|
m_lSecureTrade_Add_Off2 = Val;
|
|
m_bSecureTrade_Add_Off2 = true;
|
|
}
|
|
|
|
if (m_bSecureTrade_Add && m_bSecureTrade_Add_Off1 && m_bSecureTrade_Add_Off2 && m_bAllYourBase)
|
|
{
|
|
SetHookEx(eSecureTrade_Add);
|
|
}
|
|
|
|
|
|
if (QueryMemLoc(BSTRT( "GetSkillInfo" ), &Val) == S_OK)
|
|
{
|
|
m_lGetSkillInfo = Val;
|
|
m_bGetSkillInfo = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "GetVitalInfo" ), &Val) == S_OK)
|
|
{
|
|
m_lGetVitalInfo = Val;
|
|
m_bGetVitalInfo = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "GetAttributeInfo" ), &Val) == S_OK)
|
|
{
|
|
m_lGetAttributeInfo = Val;
|
|
m_bGetAttributeInfo = true;
|
|
}
|
|
|
|
|
|
/* I don't believe the vTable is used for any of these, however, if it becomes necessary
|
|
the functionality is here to a) detect the problem (crash at 0xFF......), and fix it
|
|
without requiring a complete update to Decal */
|
|
if (QueryMemLoc(BSTRT( "GetSkillInfo_vT" ), &Val) == S_OK)
|
|
{
|
|
m_lGetSkillInfo_vT = Val;
|
|
}
|
|
else
|
|
{
|
|
m_lGetSkillInfo_vT = 0xFF111111;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "GetVitalInfo_vT" ), &Val) == S_OK)
|
|
{
|
|
m_lGetVitalInfo_vT = Val;
|
|
}
|
|
else
|
|
{
|
|
m_lGetVitalInfo_vT = 0xFF222222;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "GetAttributeInfo_vT" ), &Val) == S_OK)
|
|
{
|
|
m_lGetAttributeInfo_vT = Val;
|
|
}
|
|
else
|
|
{
|
|
m_lGetAttributeInfo_vT = 0xFF333333;
|
|
}
|
|
|
|
if (m_lVitalBase) {
|
|
if (m_bGetSkillInfo) {
|
|
SetHookEx(eSkillInfo);
|
|
}
|
|
if (m_bGetVitalInfo) {
|
|
SetHookEx(eVitalInfo);
|
|
}
|
|
if (m_bGetAttributeInfo) {
|
|
SetHookEx(eAttributeInfo);
|
|
}
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "ToolTextHJ" ), &Val) == S_OK)
|
|
{
|
|
m_lToolTextHJ = Val;
|
|
|
|
g_lToolTextProc = HookCall( m_lToolTextHJ, (DWORD)CatchToolText );
|
|
|
|
SetHookEx( eToolText );
|
|
m_bToolTextHook = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "ToolText2HJ" ), &Val) == S_OK)
|
|
{
|
|
m_lToolText2HJ = Val;
|
|
|
|
g_lToolText2Proc = HookCall( m_lToolText2HJ, (DWORD)CatchToolTextAppend );
|
|
|
|
SetHookEx( eToolText2 );
|
|
m_bToolText2Hook = true;
|
|
}
|
|
|
|
DWORD dwOldProtect;
|
|
if( QueryMemLoc( BSTRT( "OnChatText" ), &Val ) == S_OK )
|
|
{
|
|
VirtualProtect( reinterpret_cast< void * >( Val ), 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
|
|
*reinterpret_cast< long * >( Val ) = ( reinterpret_cast< long >( OnChatText ) - ( Val + 0x4 ) );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "OnChatMessage" ), &Val ) == S_OK )
|
|
{
|
|
VirtualProtect( reinterpret_cast< void * >( Val ), 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
|
|
*reinterpret_cast< long * >( Val ) = ( reinterpret_cast< long >( OnChatMessage ) - ( Val + 0x4 ) );
|
|
}
|
|
|
|
m_Hooks |= eHooksAvailEx;
|
|
|
|
if( QueryMemLoc( BSTRT( "SelectItemHook" ), &Val ) == S_OK )
|
|
{
|
|
m_lSelectItemHook = Val;
|
|
m_bSelectItemHook = true;
|
|
g_lSelectItemHijackProc = HookCall( m_lSelectItemHook, (DWORD) SelectItemHook );
|
|
SetHookEx( eOnSelectItemEvent );
|
|
}
|
|
|
|
|
|
bool m_bUstAddItem = false;
|
|
bool m_bUstAddItem_Off1 = false;
|
|
bool m_bUstAddItem_Off2 = false;
|
|
if (QueryMemLoc(BSTRT( "UstAddItem" ), &Val) == S_OK)
|
|
{
|
|
m_lUstAddItem = Val;
|
|
m_bUstAddItem = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "UstAddItem_Off1" ), &Val) == S_OK)
|
|
{
|
|
m_lUstAddItem_Off1 = Val;
|
|
m_bUstAddItem_Off1 = true;
|
|
}
|
|
|
|
if (QueryMemLoc(BSTRT( "UstAddItem_Off2" ), &Val) == S_OK)
|
|
{
|
|
m_lUstAddItem_Off2 = Val;
|
|
m_bUstAddItem_Off2 = true;
|
|
}
|
|
|
|
if (m_bUstAddItem && m_bUstAddItem_Off1 && m_bUstAddItem_Off2 && m_bChatMessageAddy)
|
|
{
|
|
SetHookEx(eUstAddItem);
|
|
m_bUstAddItem_Useable = true;
|
|
}
|
|
|
|
m_lRequestShortcircuit1 = 0;
|
|
m_lRequestShortcircuit2 = 0;
|
|
m_lRequestShortcircuit3 = 0;
|
|
|
|
if( QueryMemLoc( BSTRT( "RequestShortcircuit1" ), &Val ) == S_OK )
|
|
m_lRequestShortcircuit1 = Val;
|
|
if( QueryMemLoc( BSTRT( "RequestShortcircuit2" ), &Val ) == S_OK )
|
|
m_lRequestShortcircuit2 = Val;
|
|
if( QueryMemLoc( BSTRT( "RequestShortcircuit3" ), &Val ) == S_OK )
|
|
m_lRequestShortcircuit3 = Val;
|
|
|
|
if( m_lRequestShortcircuit1 && m_lRequestShortcircuit2 && m_lRequestShortcircuit3 )
|
|
{
|
|
DWORD dwHook1 = HookCall( m_lRequestShortcircuit1, (DWORD) IdentifyShortcircuit );
|
|
DWORD dwHook2 = HookCall( m_lRequestShortcircuit2, (DWORD) IdentifyShortcircuit );
|
|
DWORD dwHook3 = HookCall( m_lRequestShortcircuit3, (DWORD) IdentifyShortcircuit );
|
|
|
|
if( dwHook1 && dwHook2 && dwHook3 && (dwHook1 == dwHook2) && (dwHook2 == dwHook3) )
|
|
{
|
|
m_bRequestShortcircuit = true;
|
|
g_lIdentifyHijackProc = dwHook1;
|
|
}
|
|
|
|
else
|
|
{
|
|
// Something's wrong.
|
|
HookCall( m_lRequestShortcircuit1, dwHook1 );
|
|
HookCall( m_lRequestShortcircuit2, dwHook2 );
|
|
HookCall( m_lRequestShortcircuit3, dwHook3 );
|
|
}
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "IdleTime" ), &Val ) == S_OK )
|
|
{
|
|
m_lIdleLoc = Val;
|
|
m_bIdleLoc = true;
|
|
SetHookEx( eSetIdleTime );
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "SlashDay" ), &Val ) == S_OK )
|
|
{
|
|
m_lSlashDay = Val;
|
|
m_bSlashDay = true;
|
|
SetHookEx( eSetDay );
|
|
}
|
|
}
|
|
|
|
cACHooks::~cACHooks()
|
|
{
|
|
_bstr_t _Unnamed;
|
|
|
|
delete [] g_szTimestampFormat;
|
|
|
|
long Val, lCall1 = 0, lCall2 = 0;
|
|
if( QueryMemLoc( BSTRT( "ObjectDestroyed_Call1"), &Val ) == S_OK )
|
|
{
|
|
lCall1 = Val;
|
|
}
|
|
|
|
if( QueryMemLoc( BSTRT( "ObjectDestroyed_Call2"), &Val ) == S_OK )
|
|
{
|
|
lCall2 = Val;
|
|
}
|
|
|
|
if (lCall1 && lCall2)
|
|
{
|
|
HookCall( lCall1, g_lObjectDestroyedProc );
|
|
HookCall( lCall2, g_lObjectDestroyedProc );
|
|
}
|
|
|
|
if( m_bRequestShortcircuit )
|
|
{
|
|
HookCall( m_lRequestShortcircuit1, g_lIdentifyHijackProc );
|
|
HookCall( m_lRequestShortcircuit2, g_lIdentifyHijackProc );
|
|
HookCall( m_lRequestShortcircuit3, g_lIdentifyHijackProc );
|
|
}
|
|
|
|
if( m_bToolTextHook )
|
|
{
|
|
HookCall( m_lToolTextHJ, g_lToolTextProc );
|
|
}
|
|
|
|
if( m_bToolText2Hook )
|
|
{
|
|
HookCall( m_lToolText2HJ, g_lToolText2Proc );
|
|
}
|
|
|
|
s_pACHooks = NULL;
|
|
g_lObjectDestroyedProc = 0;
|
|
|
|
if( m_bDecalRef )
|
|
m_pDecal.Release();
|
|
|
|
if( m_bIdQueueRef )
|
|
m_pIdQueue.Release();
|
|
}
|
|
|
|
void cACHooks::DecryptXML( const char *szPath, std::string &szXML )
|
|
{
|
|
if( szPath == NULL )
|
|
{
|
|
szXML = "";
|
|
return;
|
|
}
|
|
|
|
FILE *f = fopen( szPath, "rb" );
|
|
if( f == NULL )
|
|
{
|
|
szXML = "";
|
|
return;
|
|
}
|
|
|
|
szXML.clear();
|
|
unsigned char szBuffer[1025];
|
|
|
|
try
|
|
{
|
|
CCryptProv crypt;
|
|
if( crypt.Initialize( PROV_RSA_FULL, "Decal_Memlocs", MS_DEF_PROV ) == NTE_BAD_KEYSET )
|
|
crypt.Initialize( PROV_RSA_FULL, "Decal_Memlocs", MS_DEF_PROV, CRYPT_NEWKEYSET );
|
|
|
|
CCryptMD5Hash hash;
|
|
hash.Initialize( crypt );
|
|
hash.AddString( DECAL_KEY );
|
|
|
|
CCryptDerivedKey key;
|
|
key.Initialize( crypt, hash );
|
|
|
|
DWORD dwDecLen = 0;
|
|
|
|
while( ! feof(f) )
|
|
{
|
|
memset( szBuffer, 0, sizeof( szBuffer ) );
|
|
dwDecLen = fread( szBuffer, 1, 1024, f );
|
|
key.Decrypt( feof(f), (BYTE *) szBuffer, &dwDecLen );
|
|
szXML += (char *)szBuffer;
|
|
}
|
|
|
|
key.Destroy();
|
|
hash.Destroy();
|
|
crypt.Release();
|
|
}
|
|
|
|
catch( ... )
|
|
{
|
|
// crap...
|
|
szXML = "";
|
|
}
|
|
|
|
fclose( f );
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetDecal( IUnknown *pDecal )
|
|
{
|
|
if( m_bDecalRef )
|
|
{
|
|
m_pDecal.Release();
|
|
m_bDecalRef = false;
|
|
}
|
|
|
|
if( pDecal->QueryInterface( __uuidof( IDecal ), reinterpret_cast< void ** >( &m_pDecal ) ) == S_OK )
|
|
m_bDecalRef = true;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::QueryMemLoc(BSTR bstrName, long *pVal)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
if( m_bMismatch )
|
|
{
|
|
*pVal = NULL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
std::string queryName = OLE2A( bstrName );
|
|
|
|
LocMap::iterator i = m_mLocationList.find( queryName );
|
|
if( i != m_mLocationList.end() )
|
|
{
|
|
*pVal = i->second.Location;
|
|
return S_OK;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_CurrentSelection( long *pVal )
|
|
{
|
|
if( !m_bCurrentSelect )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lCurrentSelect[0] ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::put_CurrentSelection(long newVal)
|
|
{
|
|
if( !m_bCurrentSelect )
|
|
return S_FALSE;
|
|
|
|
*( reinterpret_cast< long * >( m_lCurrentSelect[0] ) ) = newVal;
|
|
*( reinterpret_cast< long * >( m_lCurrentSelect[1] ) ) = newVal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_PreviousSelection(long *pVal)
|
|
{
|
|
if( !m_bPrevSelect )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lPrevSelect[0] ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::put_PreviousSelection(long newVal)
|
|
{
|
|
if( !m_bPrevSelect )
|
|
return S_FALSE;
|
|
|
|
*( reinterpret_cast< long * >( m_lPrevSelect[0] ) ) = newVal;
|
|
*( reinterpret_cast< long * >( m_lPrevSelect[1] ) ) = newVal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/* Heyus - 23 March 2003 */
|
|
// Should be the method by which all functions write text to the chat window
|
|
// Writes raw text (does not append \n). chatMessageArg1 and 2 are the first two
|
|
// arguments you normally pass to pfnOldChatMessage. THIS SHOULD NOT BE CALLED BY
|
|
// PLUGINS/FILTERS UNLESS ABSOLUTELY NECESSARY.
|
|
// Will implement IKitchenSink later
|
|
void InternalRawWriteToChat( char* pText, long lColor, int chatMessageArg1, int chatMessageArg2 )
|
|
{
|
|
if( pText == NULL )
|
|
return;
|
|
|
|
if( g_bTimestamp )
|
|
{
|
|
bool bDoTimeStamp = (g_charBufferPreviousCall == '\n') ? true : false;
|
|
int iStrLen = strlen( pText );
|
|
|
|
char *szTimeStamp = new char[ iStrLen + 2 ];
|
|
memset( szTimeStamp, 0, iStrLen + 2 );
|
|
|
|
// Copy into a larger buffer to accomodate a possible \n
|
|
// If i were more awake, I'd see if this could just be replaced with
|
|
// g_charBufferPreviousCall = pText[strlen(pText)]
|
|
int iOffset = 0;
|
|
char *szTemp = pText;
|
|
while( *szTemp != 0 )
|
|
{
|
|
szTimeStamp[ iOffset++ ] = *szTemp;
|
|
g_charBufferPreviousCall = *szTemp;
|
|
szTemp++;
|
|
}
|
|
|
|
// Format a time stamp
|
|
char szFormattedTimestamp[ MAX_PATH ];
|
|
memset( szFormattedTimestamp, 0, MAX_PATH );
|
|
|
|
time_t stTmpTime;
|
|
time( &stTmpTime );
|
|
|
|
tm *tmTime = localtime( &stTmpTime );
|
|
long lFormattedStampLength = (long) strftime( szFormattedTimestamp, MAX_PATH, g_szTimestampFormat, tmTime );
|
|
|
|
while( *szTimeStamp != NULL && *szTimeStamp == '\n' )
|
|
{
|
|
pfnOldChatMessage( chatMessageArg1, chatMessageArg2, "\n", lColor );
|
|
g_charBufferPreviousCall = '\n';
|
|
*szTimeStamp++;
|
|
}
|
|
|
|
char* szToken = strtok( szTimeStamp, _T( "\n" ) );
|
|
|
|
char* toWrite;
|
|
|
|
if( g_lTimestampColor != 0xFFFFFFFF )
|
|
lFormattedStampLength = 0;
|
|
|
|
while( szToken != NULL )
|
|
{
|
|
int len = strlen( szToken ) + lFormattedStampLength + 3;
|
|
toWrite = new char[ len ];
|
|
memset( toWrite, 0, len );
|
|
|
|
if( bDoTimeStamp )
|
|
{
|
|
if( g_lTimestampColor == 0xFFFFFFFF )
|
|
toWrite = strcat( toWrite, szFormattedTimestamp );
|
|
else
|
|
pfnOldChatMessage( chatMessageArg1, chatMessageArg2, szFormattedTimestamp, g_lTimestampColor );
|
|
}
|
|
|
|
toWrite = strcat( toWrite, szToken );
|
|
|
|
char* nextToken = strtok( NULL, "\n" );
|
|
if( nextToken != NULL || pText[strlen(pText)-1] == '\n' )
|
|
toWrite = strcat( toWrite, "\n" );
|
|
|
|
pfnOldChatMessage( chatMessageArg1, chatMessageArg2, toWrite, lColor );
|
|
szToken = nextToken;
|
|
|
|
delete[] toWrite;
|
|
}
|
|
|
|
delete[] szTimeStamp;
|
|
}
|
|
|
|
else
|
|
pfnOldChatMessage( chatMessageArg1, chatMessageArg2, pText, lColor );
|
|
|
|
return;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::ChatOut(BSTR szText, long lColor)
|
|
{
|
|
if( pfnOldChatMessage == NULL )
|
|
return S_FALSE;
|
|
|
|
DWORD *Addy = reinterpret_cast< DWORD * > ( m_lChatMessageAddy );
|
|
if( *Addy == NULL )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
|
|
char *strText = OLE2A( szText );
|
|
|
|
if( strText == NULL )
|
|
return S_FALSE;
|
|
|
|
int iStrLen = strlen( strText );
|
|
|
|
int iOffset = 0;
|
|
char* szTemp = new char[iStrLen + 2];
|
|
memset( szTemp, 0, iStrLen+2 );
|
|
strncpy( szTemp, strText, iStrLen + 2 );
|
|
strncat( szTemp, "\n", iStrLen + 2 );
|
|
InternalRawWriteToChat( szTemp, lColor, *Addy, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/* Heyus - 23 Mar 2003 - Fixed to point to the new universal function */
|
|
STDMETHODIMP cACHooks::RawChatOut(BSTR szText, long lColor)
|
|
{
|
|
if( pfnOldChatMessage == NULL )
|
|
return S_FALSE;
|
|
|
|
DWORD *Addy = reinterpret_cast< DWORD * > ( m_lChatMessageAddy );
|
|
if( *Addy == NULL )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
|
|
char *strText = OLE2A( szText );
|
|
|
|
InternalRawWriteToChat( strText, lColor, *Addy, 0 );
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetCursorPosition(long lX, long lY)
|
|
{
|
|
if( !m_bMouse )
|
|
return S_FALSE;
|
|
|
|
for( int i = 0; i < 4; i++ )
|
|
{
|
|
*(reinterpret_cast< long * >( m_lMouse[i] ) ) = lX;
|
|
*(reinterpret_cast< long * >( m_lMouse[i] + 4 ) ) = lY;
|
|
}
|
|
|
|
SetCursorPos( lX, lY );
|
|
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
*(reinterpret_cast< long * >( m_lMouse[i] ) ) = lX;
|
|
*(reinterpret_cast< long * >( m_lMouse[i] + 4 ) ) = lY;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::CastSpell(long lSpellID, long lObjectID)
|
|
{
|
|
if( !m_bCastSpell )
|
|
return S_FALSE;
|
|
|
|
long lCombatState = 4;
|
|
if( get_CombatState( &lCombatState ) == S_OK )
|
|
{
|
|
if( lCombatState != 4 ) //Must be in MAGIC MODE
|
|
return S_FALSE;
|
|
}
|
|
|
|
long lCurrentSelect;
|
|
get_CurrentSelection( &lCurrentSelect );
|
|
put_CurrentSelection( lObjectID );
|
|
|
|
typedef void(*CastPtr)( long );
|
|
CastPtr pCast = reinterpret_cast< CastPtr >( m_lCastSpell );
|
|
pCast( lSpellID );
|
|
|
|
put_CurrentSelection( lCurrentSelect );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::MoveItem(long lObjectID, long lPackID, long lSlot, VARIANT_BOOL bStack)
|
|
{
|
|
if( !m_bMoveItem )
|
|
return S_FALSE;
|
|
|
|
long lStack = 0;
|
|
if( bStack == VARIANT_TRUE )
|
|
lStack = 1;
|
|
|
|
typedef void(*MovePtr)( long, long, long, long );
|
|
MovePtr pMove = reinterpret_cast< MovePtr >( m_lMoveItem );
|
|
pMove( lObjectID, lPackID, lSlot, lStack );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SelectItem(long lObjectID)
|
|
{
|
|
if( !m_bSelectItem )
|
|
return S_FALSE;
|
|
|
|
typedef void(*SelectPtr)( long );
|
|
SelectPtr pSelect = reinterpret_cast< SelectPtr >( m_lSelectItem );
|
|
pSelect( lObjectID );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::UseItem(long lObjectID, long lUseState)
|
|
{
|
|
if( !m_bUseItem )
|
|
return S_FALSE;
|
|
|
|
__asm
|
|
{
|
|
push 0x0
|
|
push lUseState
|
|
push lObjectID
|
|
call pfnUseItem
|
|
add esp, 0x0C
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::UseItemRaw(long lObjectID, long lUseState, long lUseMethod)
|
|
{
|
|
if( !m_bUseItem )
|
|
return S_FALSE;
|
|
|
|
__asm
|
|
{
|
|
push lUseMethod
|
|
push lUseState
|
|
push lObjectID
|
|
call pfnUseItem
|
|
add esp, 0x0C
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::UseFociSpell(long UseThis, long OnThis)
|
|
{
|
|
if( !m_bUseItem )
|
|
return S_FALSE;
|
|
|
|
long lCurrentSelected;
|
|
get_CurrentSelection( &lCurrentSelected );
|
|
put_CurrentSelection( OnThis );
|
|
|
|
__asm
|
|
{
|
|
push 0x1
|
|
push 0x1
|
|
push UseThis
|
|
call pfnUseItem
|
|
add esp, 0x0C
|
|
}
|
|
|
|
put_CurrentSelection( lCurrentSelected );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_CombatState(long *pVal)
|
|
{
|
|
if( !m_bAllYourBase )
|
|
return S_FALSE;
|
|
|
|
if( !m_bCombatStateOffset )
|
|
return S_FALSE;
|
|
|
|
*pVal = *(reinterpret_cast< long * >( (*reinterpret_cast< char ** >( m_lAllYourBase )) + m_lCombatStateOffset ));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetCombatState(long pVal)
|
|
{
|
|
if( !m_bSetCombatState )
|
|
return S_FALSE;
|
|
|
|
if( (pVal < 1) || (pVal > 4) )
|
|
return E_INVALIDARG;
|
|
|
|
typedef void(__fastcall *SetCombatStatePtr)( long, long, long, long );
|
|
SetCombatStatePtr pSetCState = reinterpret_cast< SetCombatStatePtr >( m_lSetCombatState );
|
|
pSetCState( *( reinterpret_cast< long * >( m_lAllYourBase ) ), 0, pVal, 1 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_ChatState(VARIANT_BOOL *pVal)
|
|
{
|
|
if( !m_bChatState )
|
|
return S_FALSE;
|
|
|
|
long *pChatState = reinterpret_cast< long * >( m_lChatState );
|
|
if( m_bDecalRef )
|
|
{
|
|
CComPtr< IPSite > pSite;
|
|
if( m_pDecal->get_Object( _bstr_t( "services\\DecalPlugins.InjectService\\site" ), __uuidof( IPSite ), reinterpret_cast< void ** >( &pSite ) ) == S_OK )
|
|
{
|
|
if( pSite->get_Focus( pVal ) != S_OK )
|
|
*pVal = *pChatState ? VARIANT_TRUE : VARIANT_FALSE;
|
|
else
|
|
*pVal = (*pChatState || (*pVal == VARIANT_TRUE) ) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
else
|
|
*pVal = *pChatState ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
*pVal = *pChatState ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::UseItemEx(long UseThis, long OnThis)
|
|
{
|
|
if( !m_bUseItem )
|
|
return S_FALSE;
|
|
|
|
long lCurrentSelected;
|
|
get_CurrentSelection( &lCurrentSelected );
|
|
put_CurrentSelection( OnThis );
|
|
|
|
UseItem( UseThis, 1 );
|
|
|
|
put_CurrentSelection( lCurrentSelected );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::GetFellowStats(long lCharID)
|
|
{
|
|
return IDQueueAdd( lCharID );
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_SelectedStackCount(long lStackCount, long *pVal)
|
|
{
|
|
if( !m_bStackCount )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lStackCount ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::put_SelectedStackCount(long lStackCount, long newVal)
|
|
{
|
|
if( !m_bStackCount )
|
|
return S_FALSE;
|
|
|
|
*( reinterpret_cast< long * >( m_lStackCount ) ) = newVal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_VendorID(long *pVal)
|
|
{
|
|
if( !m_bVendorID )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lVendorID ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_BusyState(long *pVal)
|
|
{
|
|
if( !m_bBusyState )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lBusyState ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_BusyStateID(long *pVal)
|
|
{
|
|
if( !m_bBusyStateID )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lBusyStateID ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_PointerState(long *pVal)
|
|
{
|
|
if( !m_bPointerState )
|
|
return S_FALSE;
|
|
|
|
*pVal = *( reinterpret_cast< long * >( m_lPointerState ) );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::MoveItemEx(long lObjectID, long lDestinationID)
|
|
{
|
|
if( !m_bMoveItemEx )
|
|
return S_FALSE;
|
|
|
|
__asm
|
|
{
|
|
push 0x0
|
|
push lDestinationID
|
|
push lObjectID
|
|
call pfnMoveItemEx
|
|
add esp, 0x0C
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
long* cACHooks::GetCs(long offs)
|
|
{
|
|
if (!m_bAllYourBase) {
|
|
return NULL ;
|
|
}
|
|
// follow multiple indirection from m_lCombatState to the
|
|
long *rv = reinterpret_cast< long * >( m_lAllYourBase );
|
|
if (*rv) rv = reinterpret_cast< long * >( *rv + 0xE4 );
|
|
if (*rv) rv = reinterpret_cast< long * >( *rv + 0x160 );
|
|
if (*rv) rv = reinterpret_cast< long * >( *rv + offs);
|
|
return rv ;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Heading(double *pVal)
|
|
{
|
|
HRESULT rv = S_OK ;
|
|
if (!m_bAllYourBase) {
|
|
*pVal = 0.0 ;
|
|
return S_FALSE ;
|
|
}
|
|
long* pX = GetCs(0x6C) ;
|
|
long* pY = GetCs(0x70) ;
|
|
float fHeadingX(0) ;
|
|
float fHeadingY(0) ;
|
|
if (pX) {
|
|
fHeadingX = *(reinterpret_cast< float * >(pX)) ;
|
|
} else {
|
|
rv = S_FALSE ;
|
|
}
|
|
if (pY) {
|
|
fHeadingY = *(reinterpret_cast< float * >(pY)) ;
|
|
} else {
|
|
rv = S_FALSE ;
|
|
}
|
|
|
|
long lCardinal = 0;
|
|
|
|
if( (fHeadingX > 0) && (fHeadingY > 0) )
|
|
lCardinal = 90;
|
|
if( (fHeadingX < 0) && (fHeadingY < 0) )
|
|
lCardinal = 270;
|
|
if( (fHeadingX < 0) && (fHeadingY > 0) )
|
|
lCardinal = 270;
|
|
if( (fHeadingX > 0) && (fHeadingY < 0) )
|
|
lCardinal = 450;
|
|
|
|
*pVal = fabs( atan( fHeadingY / fHeadingX ) * 180 / 3.14159265358979323846 - 450 + lCardinal );
|
|
|
|
return rv;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Landblock(long *pVal)
|
|
{
|
|
HRESULT rv = S_OK ;
|
|
*pVal = 0 ;
|
|
if (!m_bAllYourBase) {
|
|
return S_FALSE ;
|
|
}
|
|
long *cs = GetCs(0x4C) ;
|
|
|
|
if (cs) {
|
|
*pVal = *cs ;
|
|
} else {
|
|
*pVal = rv ;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_LocationX(double *pVal)
|
|
{
|
|
HRESULT rv = S_OK ;
|
|
if (!m_bAllYourBase) {
|
|
*pVal = 0 ;
|
|
return S_FALSE ;
|
|
}
|
|
long* cs = GetCs(0x50) ;
|
|
float val(0) ;
|
|
|
|
if (cs) {
|
|
val = *(reinterpret_cast< float * >(cs));
|
|
} else {
|
|
rv = S_FALSE ;
|
|
}
|
|
*pVal = double(val) ;
|
|
|
|
return rv;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_LocationY(double *pVal)
|
|
{
|
|
HRESULT rv = S_OK ;
|
|
if (!m_bAllYourBase) {
|
|
*pVal = 0 ;
|
|
return S_FALSE ;
|
|
}
|
|
long* cs = GetCs(0x54) ;
|
|
float val(0) ;
|
|
|
|
if (cs) {
|
|
val = *(reinterpret_cast< float * >(cs));
|
|
} else {
|
|
rv = S_FALSE ;
|
|
}
|
|
*pVal = double(val) ;
|
|
|
|
return rv;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_LocationZ(double *pVal)
|
|
{
|
|
HRESULT rv = S_OK ;
|
|
if (!m_bAllYourBase) {
|
|
*pVal = 0 ;
|
|
return S_FALSE ;
|
|
}
|
|
long* cs = GetCs(0x58) ;
|
|
float val(0) ;
|
|
|
|
if (cs) {
|
|
val = *(reinterpret_cast< float * >(cs));
|
|
} else {
|
|
rv = S_FALSE ;
|
|
}
|
|
*pVal = double(val) ;
|
|
|
|
return rv ;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_HooksAvail(long *pVal) {
|
|
*pVal = m_Hooks ;
|
|
return S_OK ;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::DropItem(long lObjectID)
|
|
{
|
|
if( !m_bMoveItemEx )
|
|
return S_FALSE;
|
|
|
|
__asm
|
|
{
|
|
push 0x1
|
|
push 0x0
|
|
push lObjectID
|
|
call pfnMoveItemEx
|
|
add esp, 0x0C
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Turn to a particular heading, discovered by Madar on 8/25/2002
|
|
STDMETHODIMP cACHooks::FaceHeading (float fHeading, VARIANT_BOOL bUnknown, VARIANT_BOOL *pRetval)
|
|
{
|
|
if (!m_bFaceHeading)
|
|
{
|
|
*pRetval = VARIANT_FALSE;
|
|
return S_FALSE;
|
|
}
|
|
|
|
DWORD dwTemp = m_lFaceHeading;
|
|
|
|
DWORD ** pTemp = (DWORD **) m_lMovementThingyParent;
|
|
|
|
DWORD dwMovementThingy = pTemp[0][m_lMovementThingyOffset];
|
|
long lResult = 0;
|
|
|
|
DWORD dwSecondArg = (bUnknown == VARIANT_TRUE) ? 1 : 0;
|
|
|
|
__asm
|
|
{
|
|
mov ecx,dwMovementThingy
|
|
push dwSecondArg
|
|
push fHeading
|
|
call dwTemp
|
|
mov lResult, eax
|
|
}
|
|
|
|
*pRetval = lResult ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Set auto-run, discovered by Madar on 9/16/2002
|
|
STDMETHODIMP cACHooks::SetAutorun (VARIANT_BOOL bOnOff)
|
|
{
|
|
if (!m_bSetAutorun)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
DWORD dwTemp = m_lSetAutorun;
|
|
|
|
DWORD ** pTemp = (DWORD **) m_lMovementThingyParent;
|
|
|
|
DWORD dwMovementThingy = pTemp[0][m_lMovementThingyOffset];
|
|
|
|
long lFirstArg = (bOnOff == VARIANT_TRUE) ? 1 : 0;
|
|
long lUnknown = 1;
|
|
|
|
__asm
|
|
{
|
|
mov ecx,dwMovementThingy
|
|
push lUnknown
|
|
push lFirstArg
|
|
call dwTemp
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::ItemIsKnown(long lGUID, VARIANT_BOOL* pRetval)
|
|
{
|
|
if (!m_bObjectFromGuid)
|
|
{
|
|
*pRetval = VARIANT_FALSE;
|
|
return S_FALSE;
|
|
}
|
|
|
|
DWORD dwTemp = m_lObjectFromGuid ;
|
|
DWORD dwClass = *((DWORD*) m_lObjectFromGuidClass);
|
|
|
|
long lResult = 0;
|
|
|
|
__asm
|
|
{
|
|
mov ecx,dwClass
|
|
push lGUID
|
|
call dwTemp
|
|
mov lResult, eax
|
|
}
|
|
|
|
*pRetval = lResult ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP cACHooks::get_Area3DWidth(long *pVal)
|
|
{
|
|
if( !m_bArea3DWidth )
|
|
return S_FALSE;
|
|
|
|
*pVal = *m_lpArea3DWidth;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Area3DHeight(long *pVal)
|
|
{
|
|
if( !m_bArea3DHeight )
|
|
return S_FALSE;
|
|
|
|
*pVal = *m_lpArea3DHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SendTell( long lPlayerID, BSTR Message )
|
|
{
|
|
if( !(m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToID) )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( Message );
|
|
|
|
long retval;
|
|
qString Msg;
|
|
pfnInternalStringConstructor( &Msg, 0, szText );
|
|
retval = pfnSendMessageToID( &Msg, lPlayerID );
|
|
pfnInternalStringDestructor( &Msg );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SendTellEx( BSTR Name, BSTR Message )
|
|
{
|
|
if( !(m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToName) )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szName = OLE2A( Name );
|
|
char *szText = OLE2A( Message );
|
|
|
|
long retval;
|
|
qString qSName;
|
|
qString qSMsg;
|
|
pfnInternalStringConstructor( &qSMsg, 0, szText );
|
|
pfnInternalStringConstructor( &qSName, 0, szName );
|
|
retval = pfnSendMessageToName( &qSMsg, &qSName );
|
|
pfnInternalStringDestructor( &qSMsg );
|
|
pfnInternalStringDestructor( &qSName );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::LocalChatText(BSTR Text)
|
|
{
|
|
if( !(m_bInternalStringConstructor && m_bInternalStringDestructor && m_bLocalChatText) )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( Text );
|
|
|
|
qString qSText;
|
|
|
|
pfnInternalStringConstructor( &qSText, 0, szText );
|
|
pfnLocalChatText( &qSText );
|
|
pfnInternalStringDestructor( &qSText );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::LocalChatEmote(BSTR EmoteText)
|
|
{
|
|
if( !(m_bInternalStringConstructor && m_bInternalStringDestructor && m_bLocalChatEmote) )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( EmoteText );
|
|
|
|
qString qSText;
|
|
|
|
pfnInternalStringConstructor( &qSText, 0, szText );
|
|
pfnLocalChatEmote( &qSText );
|
|
pfnInternalStringDestructor( &qSText );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Vital(long Vital, long* pVal)
|
|
{
|
|
if( !(m_bGetVital && m_lVitalBase) )
|
|
return S_FALSE;
|
|
|
|
if( (Vital < 1) || (Vital > 9) )
|
|
return E_INVALIDARG;
|
|
|
|
long lBaseOrBuffed = (Vital > 6) ? 1 : 0;
|
|
if( lBaseOrBuffed )
|
|
{
|
|
if( Vital == 7 ) // health
|
|
Vital = 2;
|
|
else if( Vital == 8 ) // stamina
|
|
Vital = 4;
|
|
else if( Vital == 9 ) // mana
|
|
Vital = 6;
|
|
}
|
|
|
|
long ( __fastcall *Internal_GetStat )( qPointerList *, long, long, long *, long ) = reinterpret_cast< long ( __fastcall * )( qPointerList *, long, long, long *, long ) >( m_lGetVital );
|
|
|
|
qPointerList *p = reinterpret_cast< qPointerList * >( m_lVitalBase );
|
|
p = p->dd[0];
|
|
|
|
Internal_GetStat( p, 0, Vital, pVal, lBaseOrBuffed );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Attribute(long Attribute, long* pVal)
|
|
{
|
|
if( !(m_bGetAttribute && m_lVitalBase) )
|
|
return S_FALSE;
|
|
|
|
if( (Attribute < 1) || (Attribute > 12) )
|
|
return E_INVALIDARG;
|
|
|
|
long lBaseOrBuffed = (Attribute > 6) ? 1 : 0;
|
|
if( lBaseOrBuffed )
|
|
Attribute -= 6;
|
|
|
|
qPointerList *p = reinterpret_cast< qPointerList * >( m_lVitalBase );
|
|
p = p->dd[0];
|
|
|
|
long ( __fastcall *Internal_GetAttribute )( qPointerList *, long, long, long *, long ) = reinterpret_cast< long ( __fastcall * )( qPointerList *, long, long, long *, long ) >( m_lGetAttribute );
|
|
|
|
Internal_GetAttribute( p, 0, Attribute, pVal, lBaseOrBuffed );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_Skill(long Skill, long* pVal)
|
|
{
|
|
if( !(m_bGetSkill && m_lVitalBase) )
|
|
return S_FALSE;
|
|
|
|
// error on out of range, the unused range for added skills, and other skill ids that Turbine skips
|
|
if((Skill < 1) || (Skill > 89) || ((Skill > 39) && (Skill < 50)) || (Skill == 8 ) || (Skill == 58) || (Skill == 17) || (Skill == 67) || (Skill == 25) || (Skill == 75) || (Skill == 26) || (Skill == 76))
|
|
return E_INVALIDARG;
|
|
|
|
long lBaseOrBuffed = (Skill > 50) ? 1 : 0;
|
|
if( lBaseOrBuffed )
|
|
Skill -= 50;
|
|
|
|
qPointerList *p = reinterpret_cast< qPointerList * >( m_lVitalBase );
|
|
p = p->dd[0];
|
|
|
|
long ( __fastcall *Internal_GetSkill )( qPointerList *, long, long, long *, long ) = reinterpret_cast< long ( __fastcall * )( qPointerList *, long, long, long *, long ) >( m_lGetSkill );
|
|
|
|
Internal_GetSkill( p, 0, Skill, pVal, lBaseOrBuffed );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_HooksAvailEx(eAvailableHooksEx HookID, VARIANT_BOOL *pVal)
|
|
{
|
|
unsigned int ID;
|
|
unsigned int Index, Offset;
|
|
|
|
// Default to not being valid
|
|
*pVal = VARIANT_FALSE;
|
|
|
|
// Convert the enum to an integer so we can do maths on it
|
|
ID = static_cast< unsigned int >( HookID );
|
|
|
|
// Ensure the value is within range
|
|
if( ID > m_HookCount )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// Extract the index and bit offset
|
|
Index = ID >> 5; // 32 -> 5 bits
|
|
Offset = ID & 0x1F; // 1F -> 5 bits worth of 1s
|
|
|
|
if( m_HooksEx[Index] & (1 << Offset) )
|
|
{
|
|
*pVal = VARIANT_TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::Logout()
|
|
{
|
|
if( m_bLogout )
|
|
{
|
|
long ( __cdecl *Internal_Logout )( long );
|
|
Internal_Logout = reinterpret_cast< long ( __cdecl * )( long ) >( m_lLogout );
|
|
Internal_Logout(0);
|
|
return S_OK;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::ToolText(BSTR Text, VARIANT_BOOL bError)
|
|
{
|
|
/*
|
|
Moputu - 09012003: Added to allow plugins to display text
|
|
in the upper left hand corner as either white text w/o sound or
|
|
as yellow text with the busy/error sound.
|
|
|
|
Either CombatState or ObjectBase can be used as the starting
|
|
memloc as both always seems to have the same value and the
|
|
function is called using one or the other in the client.exe.
|
|
You can only find the function address after the player is logged in.
|
|
*/
|
|
|
|
if( !m_bAllYourBase ) //the combat state memloc is necessary
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( Text ); //pointer to the text being passed
|
|
DWORD cstate = *((long *)m_lAllYourBase);
|
|
|
|
long lErr;
|
|
if (bError)
|
|
lErr = 1; // display text as yellow w/sound
|
|
else
|
|
lErr = 0; // display text as white w/o sound
|
|
|
|
__asm
|
|
{
|
|
mov ecx, cstate
|
|
|
|
push lErr
|
|
push szText
|
|
|
|
mov edx, dword ptr [ecx]
|
|
call dword ptr [edx+114h]
|
|
add esp, 8
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::ToolTextAppend(BSTR Text, VARIANT_BOOL bError)
|
|
{
|
|
if( !m_bAllYourBase ) //the combat state memloc is necessary
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( Text ); //pointer to the text being passed
|
|
DWORD cstate = *((long *)m_lAllYourBase);
|
|
|
|
long lErr;
|
|
if (bError)
|
|
lErr = 1; // display text as yellow w/sound
|
|
else
|
|
lErr = 0; // display text as white w/o sound
|
|
|
|
__asm
|
|
{
|
|
mov ecx, cstate
|
|
|
|
push lErr
|
|
push szText
|
|
|
|
mov edx, dword ptr [ecx]
|
|
call dword ptr [edx+118h]
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SecureTrade_Add(long ItemID, VARIANT_BOOL *pVal)
|
|
{
|
|
void ( __fastcall *Internal_SecureTrade_Add )( struct qPointerList *, int, long );
|
|
struct qPointerList *p;
|
|
VARIANT_BOOL ItemExists;
|
|
|
|
if (pVal) /* Should probably return an error code. Tough. */
|
|
{
|
|
*pVal = VARIANT_FALSE;
|
|
}
|
|
|
|
else
|
|
return E_FAIL;
|
|
|
|
if ( m_bSecureTrade_Add && m_bSecureTrade_Add_Off1 && m_bSecureTrade_Add_Off2 && m_bAllYourBase )
|
|
{
|
|
if( ItemIsKnown(ItemID, &ItemExists) != S_OK )
|
|
return E_FAIL;
|
|
|
|
if (ItemExists == VARIANT_FALSE)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
p = (qPointerList *)m_lAllYourBase;
|
|
if (!p)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
p = p->dd[0];
|
|
if (!p)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
p = p->dd[m_lSecureTrade_Add_Off1 >> 2];
|
|
if (!p)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
p = p->dd[m_lSecureTrade_Add_Off2 >> 2];
|
|
if (!p)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
Internal_SecureTrade_Add = reinterpret_cast< void ( __fastcall *)( struct qPointerList *, int, long ) >( m_lSecureTrade_Add );
|
|
Internal_SecureTrade_Add(p, 0, ItemID);
|
|
if (pVal)
|
|
{
|
|
*pVal = VARIANT_TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT cACHooks::GetSkillInfo(eSkill SkillID, struct qSkill *Skill) {
|
|
int ( __fastcall *Internal_GetSkillInfo )( void *, int, int, struct qSkill * );
|
|
|
|
if (!m_bGetSkillInfo) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (SkillID > 50) {
|
|
SkillID = (eSkill)(SkillID - 50);
|
|
}
|
|
if ((SkillID < 1) || (SkillID > 50)) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
Skill->vTable = m_lGetSkillInfo_vT;
|
|
|
|
Internal_GetSkillInfo = reinterpret_cast< int (__fastcall*)(void *, int, int, struct qSkill *) >(m_lGetSkillInfo);
|
|
if (Internal_GetSkillInfo(*(void **)m_lVitalBase, 0, SkillID, Skill)) {
|
|
return S_OK;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT cACHooks::GetAttributeInfo(eAttribute AttributeID, struct qAttribute *Attribute) {
|
|
int (__fastcall *Internal_GetAttributeInfo)(void *, int, int, struct qAttribute *);
|
|
|
|
if (!m_bGetAttributeInfo) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (AttributeID > 6) {
|
|
AttributeID = (eAttribute)(AttributeID - 6);
|
|
}
|
|
if ((AttributeID < 1) || (AttributeID > 6)) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
Attribute->vTable = m_lGetAttributeInfo_vT;
|
|
|
|
Internal_GetAttributeInfo = reinterpret_cast< int (__fastcall*)(void *, int, int, struct qAttribute *) >(m_lGetAttributeInfo);
|
|
if (Internal_GetAttributeInfo(*(void **)m_lVitalBase, 0, AttributeID, Attribute)) {
|
|
return S_OK;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT cACHooks::GetVitalInfo(eVital VitalID, struct qVital *Vital) {
|
|
int (__fastcall *Internal_GetVitalInfo)(void *, int, int, struct qVital *);
|
|
|
|
if (!m_bGetVitalInfo) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
switch (VitalID) {
|
|
case eCurrentHealth:
|
|
case eMaximumHealth:
|
|
case eBaseHealth:
|
|
VitalID = eCurrentHealth;
|
|
break;
|
|
case eCurrentStamina:
|
|
case eMaximumStamina:
|
|
case eBaseStamina:
|
|
VitalID = eCurrentStamina;
|
|
break;
|
|
case eCurrentMana:
|
|
case eMaximumMana:
|
|
case eBaseMana:
|
|
VitalID = eCurrentMana;
|
|
break;
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
Vital->vTable = m_lGetVitalInfo_vT;
|
|
|
|
Internal_GetVitalInfo = reinterpret_cast< int (__fastcall*)(void *, int, int, struct qVital *) >(m_lGetVitalInfo);
|
|
if (Internal_GetVitalInfo(*(void **)m_lVitalBase, 0, VitalID, Vital)) {
|
|
return S_OK;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_SkillTrainLevel( eSkill SkillID, eTrainLevel *pVal )
|
|
{
|
|
struct qSkill Skill;
|
|
HRESULT hr;
|
|
hr = GetSkillInfo(SkillID, &Skill);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Skill.Trained;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_SkillTotalXP( eSkill SkillID, int *pVal )
|
|
{
|
|
struct qSkill Skill;
|
|
HRESULT hr;
|
|
hr = GetSkillInfo(SkillID, &Skill);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Skill.TotalXP;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_SkillFreePoints( eSkill SkillID, int *pVal )
|
|
{
|
|
struct qSkill Skill;
|
|
HRESULT hr;
|
|
hr = GetSkillInfo(SkillID, &Skill);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Skill.FreePoints;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP cACHooks::get_SkillClicks( eSkill SkillID, int *pVal )
|
|
{
|
|
struct qSkill Skill;
|
|
HRESULT hr;
|
|
hr = GetSkillInfo(SkillID, &Skill);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Skill.Clicks;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_AttributeClicks( eAttribute AttributeID, int *pVal )
|
|
{
|
|
struct qAttribute Attribute;
|
|
HRESULT hr;
|
|
hr = GetAttributeInfo(AttributeID, &Attribute);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Attribute.Clicks;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_AttributeTotalXP( eAttribute AttributeID, int *pVal )
|
|
{
|
|
struct qAttribute Attribute;
|
|
HRESULT hr;
|
|
hr = GetAttributeInfo(AttributeID, &Attribute);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Attribute.TotalXP;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP cACHooks::get_AttributeStart( eAttribute AttributeID, int *pVal )
|
|
{
|
|
struct qAttribute Attribute;
|
|
HRESULT hr;
|
|
hr = GetAttributeInfo(AttributeID, &Attribute);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Attribute.Start;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_VitalClicks( eVital VitalID, int *pVal )
|
|
{
|
|
struct qVital Vital;
|
|
HRESULT hr;
|
|
hr = GetVitalInfo(VitalID, &Vital);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Vital.Clicks;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::get_VitalTotalXP( eVital VitalID, int *pVal )
|
|
{
|
|
struct qVital Vital;
|
|
HRESULT hr;
|
|
hr = GetVitalInfo(VitalID, &Vital);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
*pVal = Vital.TotalXP;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void cACHooks::SetHookEx( eAvailableHooksEx HookID )
|
|
{
|
|
unsigned int ID;
|
|
unsigned int Index, Offset;
|
|
|
|
ID = static_cast< unsigned int >( HookID );
|
|
|
|
Index = ID >> 5;
|
|
Offset = ID & 0x1F;
|
|
|
|
_ASSERTE( Index < (sizeof(m_HooksEx) / sizeof(m_HooksEx[0])) );
|
|
|
|
m_HooksEx[Index] |= (1 << Offset);
|
|
|
|
if( ID > m_HookCount )
|
|
m_HookCount = ID;
|
|
|
|
return;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetIdleTime( double dIdleTimeout )
|
|
{
|
|
if( !m_bIdleLoc )
|
|
return S_FALSE;
|
|
|
|
DWORD dwOldProtect = 0;
|
|
DWORD dwNewProtect = PAGE_READWRITE;
|
|
VirtualProtect( reinterpret_cast< void * >( m_lIdleLoc ), 8 /* sizeof double */, dwNewProtect, &dwOldProtect );
|
|
*( reinterpret_cast< double * >( m_lIdleLoc ) ) = dIdleTimeout;
|
|
VirtualProtect( reinterpret_cast< void * >( m_lIdleLoc ), 8 /* sizeof double */, dwOldProtect, &dwNewProtect );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void cACHooks::InternalObjectDestroyed (DWORD dwGuid)
|
|
{
|
|
Fire_ObjectDestroyed( dwGuid );
|
|
}
|
|
|
|
void cACHooks::InternalSelectItem( DWORD dwID )
|
|
{
|
|
Fire_OnSelectItem( dwID );
|
|
}
|
|
|
|
void cACHooks::InternalShortcircuit( DWORD dwID )
|
|
{
|
|
if( m_bIdQueueRef )
|
|
m_pIdQueue->ShortcircuitID( dwID );
|
|
}
|
|
|
|
void OnObjectDestroyed (DWORD dwGuid)
|
|
{
|
|
if( cACHooks::s_pACHooks )
|
|
cACHooks::s_pACHooks->InternalObjectDestroyed( dwGuid );
|
|
}
|
|
|
|
void OnSelectItem( DWORD dwID )
|
|
{
|
|
if( cACHooks::s_pACHooks )
|
|
cACHooks::s_pACHooks->InternalSelectItem( dwID );
|
|
}
|
|
|
|
void Shortcircuit( DWORD dwID )
|
|
{
|
|
if( cACHooks::s_pACHooks )
|
|
cACHooks::s_pACHooks->InternalShortcircuit( dwID );
|
|
}
|
|
|
|
void __declspec(naked) SelectItemHook()
|
|
{
|
|
_asm
|
|
{
|
|
push eax
|
|
call OnSelectItem
|
|
add esp,4
|
|
|
|
jmp g_lSelectItemHijackProc
|
|
}
|
|
}
|
|
|
|
void __declspec(naked) ObjectDestroyedHook()
|
|
{
|
|
_asm
|
|
{
|
|
mov eax,[esp+8]
|
|
push eax
|
|
push ecx
|
|
|
|
push eax
|
|
call OnObjectDestroyed
|
|
|
|
add esp,4
|
|
pop ecx
|
|
pop eax
|
|
mov [esp+8],eax
|
|
|
|
jmp g_lObjectDestroyedProc
|
|
}
|
|
}
|
|
|
|
void __declspec(naked) IdentifyShortcircuit()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax,[esp+4]
|
|
push eax
|
|
push ecx
|
|
|
|
push eax
|
|
call Shortcircuit
|
|
add esp, 4
|
|
|
|
pop ecx
|
|
pop eax
|
|
mov [esp+4], eax
|
|
|
|
jmp g_lIdentifyHijackProc
|
|
}
|
|
}
|
|
|
|
// Returns the function which previously was being called, after replacing it with the new call.
|
|
DWORD HookCall (DWORD dwCallAddress, DWORD dwReplacement)
|
|
{
|
|
DWORD* pTemp = (DWORD *) (dwCallAddress + 1);
|
|
|
|
HANDLE hProcess = OpenProcess
|
|
(
|
|
PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
|
|
FALSE,
|
|
GetCurrentProcessId ()
|
|
);
|
|
|
|
DWORD dwOriginal = 0;
|
|
|
|
if (hProcess)
|
|
{
|
|
dwOriginal = (*pTemp) + dwCallAddress + 5;
|
|
|
|
DWORD dwTemp = dwReplacement - (dwCallAddress + 5);
|
|
if (WriteProcessMemory
|
|
(
|
|
hProcess,
|
|
pTemp,
|
|
&dwTemp,
|
|
sizeof (DWORD),
|
|
NULL
|
|
))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
dwOriginal = 0;
|
|
}
|
|
|
|
CloseHandle (hProcess);
|
|
}
|
|
|
|
return dwOriginal;
|
|
}
|
|
|
|
bool cACHooks::InternalChatMessage( char *szText, long lColor )
|
|
{
|
|
return Fire_OnChatBoxMessage( _bstr_t( szText ), lColor ) == VARIANT_TRUE ? true : false;
|
|
}
|
|
|
|
bool cACHooks::InternalChatText( char *szText )
|
|
{
|
|
return Fire_OnCommandLineText( _bstr_t( szText ) ) == VARIANT_TRUE ? true : false;
|
|
}
|
|
|
|
bool DispatchChatMessage( char *pText, long pdwColor )
|
|
{
|
|
if( cACHooks::s_pACHooks )
|
|
return cACHooks::s_pACHooks->InternalChatMessage( pText, pdwColor );
|
|
|
|
return false;
|
|
}
|
|
|
|
bool DispatchChatText( char *pText )
|
|
{
|
|
if( cACHooks::s_pACHooks )
|
|
return cACHooks::s_pACHooks->InternalChatText( pText );
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Heyus - 23 Mar 2003 - Fixed to point to the new universal function */
|
|
void __fastcall OnChatMessage( int _ecx, int _edx, char* pText, long lColor )
|
|
{
|
|
if( !DispatchChatMessage( pText, lColor ) )
|
|
InternalRawWriteToChat( pText, lColor, _ecx, _edx );
|
|
|
|
return;
|
|
}
|
|
|
|
void __declspec(naked) OnChatText()
|
|
{
|
|
__asm
|
|
{
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, 0xC
|
|
|
|
call pfnOldChatText
|
|
|
|
mov [ebp-4], ecx
|
|
mov [ebp-8], eax
|
|
|
|
push eax
|
|
|
|
call DispatchChatText
|
|
|
|
mov edx, eax
|
|
mov ecx, [ebp-4]
|
|
mov eax, [ebp-8]
|
|
|
|
test dl, dl
|
|
jz dont_eat_chat_text
|
|
|
|
mov byte ptr [eax], 0
|
|
|
|
dont_eat_chat_text:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
}
|
|
}
|
|
|
|
void cACHooks::InternalToolText( char *szText, VARIANT_BOOL bError )
|
|
{
|
|
USES_CONVERSION;
|
|
Fire_OnToolText( T2BSTR( szText ), bError );
|
|
}
|
|
|
|
void OnToolText( char *szText, long lError )
|
|
{
|
|
VARIANT_BOOL bError = lError;
|
|
|
|
if( cACHooks::s_pACHooks )
|
|
cACHooks::s_pACHooks->InternalToolText( szText, bError );
|
|
}
|
|
|
|
void __declspec(naked) CatchToolText()
|
|
{
|
|
__asm
|
|
{
|
|
push ecx
|
|
push edx
|
|
push edi
|
|
push eax
|
|
call OnToolText
|
|
pop eax
|
|
pop edi
|
|
pop edx
|
|
pop ecx
|
|
jmp g_lToolTextProc
|
|
}
|
|
}
|
|
|
|
void cACHooks::InternalToolTextAppend( char *szText, VARIANT_BOOL bError )
|
|
{
|
|
USES_CONVERSION;
|
|
Fire_OnToolTextAppend( T2BSTR( szText ), bError );
|
|
}
|
|
|
|
void OnToolTextAppend( char *szText, long lError )
|
|
{
|
|
VARIANT_BOOL bError = lError;
|
|
|
|
if( cACHooks::s_pACHooks )
|
|
cACHooks::s_pACHooks->InternalToolTextAppend( szText, bError );
|
|
}
|
|
|
|
void __declspec(naked) CatchToolTextAppend()
|
|
{
|
|
__asm
|
|
{
|
|
push ecx
|
|
push edx
|
|
push edi
|
|
push eax
|
|
call OnToolTextAppend
|
|
pop eax
|
|
pop edi
|
|
pop edx
|
|
pop ecx
|
|
jmp g_lToolText2Proc
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::RequestID(long lObjectID)
|
|
{
|
|
if( !m_bRequestID )
|
|
return S_FALSE;
|
|
|
|
if( m_bIdQueueRef )
|
|
return m_pIdQueue->AddToQueue( lObjectID );
|
|
|
|
typedef void(*RequestPtr)( long );
|
|
RequestPtr pRequest = reinterpret_cast< RequestPtr >( m_lRequestID );
|
|
pRequest( lObjectID );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::IDQueueAdd(long lObjectID)
|
|
{
|
|
if( !m_bIdQueueRef )
|
|
return RequestID( lObjectID );
|
|
|
|
return m_pIdQueue->AddToQueue( lObjectID );
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetIDFilter(IKitchenSink* pIDFilter)
|
|
{
|
|
if( !m_bIdQueueRef )
|
|
{
|
|
m_bIdQueueRef = true;
|
|
m_pIdQueue = pIDFilter;
|
|
SetHookEx( eIDQueueAdd );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::UstAddItem(long lObjectID)
|
|
{
|
|
VARIANT_BOOL ItemExists;
|
|
|
|
if ( !m_bUstAddItem_Useable )
|
|
return S_FALSE;
|
|
|
|
if( ItemIsKnown( lObjectID, &ItemExists ) != S_OK )
|
|
return E_FAIL;
|
|
|
|
if( ItemExists == VARIANT_FALSE )
|
|
return S_FALSE;
|
|
|
|
//Calculate the THIS pointer
|
|
//DWORD thisPtr = *((long *)(*((long *)(*((long *)0x77A618) + 0x324)) + 0xE0));
|
|
//DWORD tmp;
|
|
//DWORD func = 0x005556C0;
|
|
|
|
DWORD thisPtr = *((long *)(*((long *)(*((long *)m_lChatMessageAddy) + m_lUstAddItem_Off1)) + m_lUstAddItem_Off2));
|
|
DWORD tmp;
|
|
DWORD func = (DWORD)m_lUstAddItem;
|
|
|
|
__asm
|
|
{
|
|
mov tmp, ecx
|
|
mov ecx, thisPtr
|
|
push lObjectID
|
|
|
|
call func
|
|
|
|
mov ecx, tmp
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SendMessageByMask( long lMask, BSTR szMessage )
|
|
{
|
|
if( !(m_bInternalStringConstructor && m_bInternalStringDestructor && m_bSendMessageToMask) )
|
|
return S_FALSE;
|
|
|
|
USES_CONVERSION;
|
|
char *szText = OLE2A( szMessage );
|
|
|
|
long retval;
|
|
qString Msg;
|
|
pfnInternalStringConstructor( &Msg, 0, szText );
|
|
retval = pfnSendMessageByMask( lMask, &Msg );
|
|
pfnInternalStringDestructor( &Msg );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cACHooks::SetDay( VARIANT_BOOL bDay )
|
|
{
|
|
if( !m_bSlashDay )
|
|
return S_FALSE;
|
|
|
|
*reinterpret_cast< long * >( m_lSlashDay ) = bDay == VARIANT_TRUE ? 1 : 0;
|
|
|
|
return S_OK;
|
|
}
|