Well this is how I get the TLS Index and Value from W3.
Code:
DWORD GetIndex()
{
return *(DWORD*)(0x6FAA45E4);
}
DWORD GetW3TlsForIndex(DWORD index)
{
DWORD pid = GetCurrentProcessId();
THREADENTRY32 te32;
HANDLE hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, pid );
te32.dwSize = sizeof(THREADENTRY32);
if ( Thread32First( hSnap, &te32 ) )
{
do
{
if ( te32.th32OwnerProcessID == pid )
{
HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, false, te32.th32ThreadID );
CONTEXT ctx = { CONTEXT_SEGMENTS };
LDT_ENTRY ldt;
GetThreadContext( hThread, &ctx );
GetThreadSelectorEntry( hThread, ctx.SegFs, &ldt );
DWORD dwThreadBase = ldt.BaseLow|(ldt.HighWord.Bytes.BaseMid<<16)|(ldt.HighWord.Bytes.BaseHi<<24);
CloseHandle( hThread );
if ( dwThreadBase == NULL )
continue;
DWORD *dwTLS = *(DWORD**)(dwThreadBase+0xE10+4*index);
printf("Thread: %X , TLS for index %X : %X\n",te32.th32ThreadID,index,(DWORD)dwTLS);
if ( dwTLS == NULL )
continue;
return (DWORD)dwTLS;
}
} while( Thread32Next( hSnap, &te32 ) );
}
return NULL;
}
And this is how I get the current game state value after having already retrieved the TlsValue:
Code:
DWORD GetGameStateValue()
{
DWORD rt;
__asm
{
MOV ESI,0x0D;
MOV EAX,TlsValue;
MOV EAX, DWORD PTR DS:[EAX+ESI*4];
MOV EAX,DWORD PTR DS:[EAX+0x10]
MOV ECX,DWORD PTR DS:[EAX+0x8]
MOV EAX, DWORD PTR DS:[ECX+0x278];
MOV rt,EAX;
}
return rt;
}
And what made me think it wasn't used prior to patch 1.22 is that I didn't find any calls to TlsGetValue/TlsSetValue in 1.21b game.dll intermodular calls.