I prefer something like what follows, but greyman did a great job of explaining everything.
Code:
void SwapTlsData(DWORD ThreadId1, DWORD ThreadId2)
{
__try
{
MMGetThreadTeb(ThreadId1)->ThreadLocalStoragePointer = MMGetThreadTeb(ThreadId2)->ThreadLocalStoragePointer;
}
__except(UnhandledExceptionFilter( GetExceptionInformation() ))
{
//ignore
}
}
PTEB MMGetCurrentTeb()
{
LPVOID pTeb = NULL;
__asm
{
mov eax,fs:[00000018h]
mov pTeb , eax
}
return (PTEB)pTeb;
}
PTEB MMGetThreadTeb(DWORD ThreadId)
{
CONTEXT Context;
LDT_ENTRY SelEntry;
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,TRUE, ThreadId);
if(!hThread)
return NULL;
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread,&Context);
GetThreadSelectorEntry(hThread, Context.SegFs, &SelEntry);
PTEB pTEB = (PTEB)(( SelEntry.HighWord.Bits.BaseHi << 24) | (SelEntry.HighWord.Bits.BaseMid << 16) | SelEntry.BaseLow);
CloseHandle(hThread);
return pTEB;
}