-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathCpuThreads.cpp
123 lines (99 loc) · 2.89 KB
/
CpuThreads.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <stdio.h>
#include <windows.h>
#include "WoWMIPS.h"
CpuThreadDataStruct Global_CpuThreadList[MAX_CPU_THREAD_COUNT];
CRITICAL_SECTION Global_CpuThreadListCriticalSection;
CpuThreadDataStruct *CPU_GetThreadData()
{
return (CpuThreadDataStruct*)TlsGetValue(dwGlobal_CpuThreadDataTlsIndex);
}
DWORD CPU_LockThreadList()
{
EnterCriticalSection(&Global_CpuThreadListCriticalSection);
return 0;
}
DWORD CPU_UnlockThreadList()
{
LeaveCriticalSection(&Global_CpuThreadListCriticalSection);
return 0;
}
CpuThreadDataStruct *CPU_AssignNewThread()
{
CpuThreadDataStruct *pCpuThreadData = NULL;
HANDLE hCurrentThread = NULL;
// check for exited threads
for(DWORD i = 0; i < MAX_CPU_THREAD_COUNT; i++)
{
if(Global_CpuThreadList[i].dwInUse != 0)
{
if(WaitForSingleObject(Global_CpuThreadList[i].hThread, 0) == WAIT_OBJECT_0)
{
// thread exited
CloseHandle(Global_CpuThreadList[i].hThread);
Global_CpuThreadList[i].dwInUse = 0;
}
}
}
// find a free slot
for(i = 0; i < MAX_CPU_THREAD_COUNT; i++)
{
if(Global_CpuThreadList[i].dwInUse == 0)
{
pCpuThreadData = &Global_CpuThreadList[i];
break;
}
}
if(pCpuThreadData == NULL)
{
return NULL;
}
if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hCurrentThread, SYNCHRONIZE, 0, 0) == 0)
{
return NULL;
}
memset((void*)pCpuThreadData, 0, sizeof(CpuThreadDataStruct));
pCpuThreadData->dwInUse = 1;
pCpuThreadData->hThread = hCurrentThread;
// store ptr in TLS
TlsSetValue(dwGlobal_CpuThreadDataTlsIndex, (void*)pCpuThreadData);
return pCpuThreadData;
}
DWORD CPU_InitialiseThread()
{
DWORD dwStackSize = 0;
BYTE *pStackData = NULL;
CpuThreadDataStruct *pCpuThreadData = NULL;
// allocate stack
dwStackSize = pGlobal_ImageNtHeader->OptionalHeader.SizeOfStackReserve;
if(pGlobal_ImageNtHeader->OptionalHeader.SizeOfStackCommit > dwStackSize)
{
dwStackSize = pGlobal_ImageNtHeader->OptionalHeader.SizeOfStackCommit;
}
pStackData = (BYTE*)malloc(dwStackSize);
if(pStackData == NULL)
{
return 1;
}
CPU_LockThreadList();
// store thread-local info
pCpuThreadData = CPU_AssignNewThread();
if(pCpuThreadData == NULL)
{
CPU_UnlockThreadList();
free(pStackData);
return 1;
}
pCpuThreadData->pWatchWritePtr = NULL;
pCpuThreadData->pStackData = pStackData;
pCpuThreadData->dwStackSize = dwStackSize;
// initialise emulated PEB structure
memset((void*)&pCpuThreadData->TEB, 0, sizeof(pCpuThreadData->TEB));
// TEB.StackBase
*(DWORD*)((DWORD)&pCpuThreadData->TEB + 4) = (DWORD)pStackData + dwStackSize;
// TEB.StackLimit
*(DWORD*)((DWORD)&pCpuThreadData->TEB + 8) = (DWORD)pStackData;
CPU_UnlockThreadList();
// set initial stack ptr
pCpuThreadData->CpuState.dwRegister[CPU_GetRegisterIndexByName("sp")] = (DWORD)pStackData + dwStackSize;
return 0;
}