Updated.
[reactos.git] / reactos / lib / kernel32 / thread / thread.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/thread/thread.c
5 * PURPOSE: Thread functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Tls functions are modified from WINE
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <windows.h>
15 #include <kernel32/thread.h>
16 #include <ddk/ntddk.h>
17 #include <string.h>
18 #include <internal/i386/segment.h>
19
20 //#define NDEBUG
21 #include <kernel32/kernel32.h>
22
23
24 /* FUNCTIONS *****************************************************************/
25
26 HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
27 DWORD dwStackSize,
28 LPTHREAD_START_ROUTINE lpStartAddress,
29 LPVOID lpParameter,
30 DWORD dwCreationFlags,
31 LPDWORD lpThreadId)
32 {
33 return(CreateRemoteThread(NtCurrentProcess(),
34 lpThreadAttributes,
35 dwStackSize,
36 lpStartAddress,
37 lpParameter,
38 dwCreationFlags,
39 lpThreadId));
40 }
41
42 HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
43 LPSECURITY_ATTRIBUTES lpThreadAttributes,
44 DWORD dwStackSize,
45 LPTHREAD_START_ROUTINE lpStartAddress,
46 LPVOID lpParameter,
47 DWORD dwCreationFlags,
48 LPDWORD lpThreadId)
49 {
50 HANDLE ThreadHandle;
51 OBJECT_ATTRIBUTES ObjectAttributes;
52 CLIENT_ID ClientId;
53 CONTEXT ThreadContext;
54 INITIAL_TEB InitialTeb;
55 BOOLEAN CreateSuspended = FALSE;
56 PVOID BaseAddress;
57 DWORD StackSize;
58 ULONG BytesWritten;
59 NTSTATUS Status;
60
61 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
62 ObjectAttributes.RootDirectory = NULL;
63 ObjectAttributes.ObjectName = NULL;
64 ObjectAttributes.Attributes = 0;
65 if (lpThreadAttributes != NULL)
66 {
67 if (lpThreadAttributes->bInheritHandle)
68 ObjectAttributes.Attributes = OBJ_INHERIT;
69 ObjectAttributes.SecurityDescriptor =
70 lpThreadAttributes->lpSecurityDescriptor;
71 }
72 ObjectAttributes.SecurityQualityOfService = NULL;
73
74 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
75 CreateSuspended = TRUE;
76 else
77 CreateSuspended = FALSE;
78
79 StackSize = (dwStackSize == 0) ? 4096 : dwStackSize;
80
81 BaseAddress = 0;
82 Status = NtAllocateVirtualMemory(hProcess,
83 &BaseAddress,
84 0,
85 (PULONG)&StackSize,
86 MEM_COMMIT,
87 PAGE_READWRITE);
88 if (!NT_SUCCESS(Status))
89 {
90 DPRINT("Could not allocate stack space!\n");
91 return NULL;
92 }
93
94 DPRINT("Stack base address: %p\n", BaseAddress);
95
96 memset(&ThreadContext,0,sizeof(CONTEXT));
97 ThreadContext.Eip = (LONG)lpStartAddress;
98 ThreadContext.SegGs = USER_DS;
99 ThreadContext.SegFs = USER_DS;
100 ThreadContext.SegEs = USER_DS;
101 ThreadContext.SegDs = USER_DS;
102 ThreadContext.SegCs = USER_CS;
103 ThreadContext.SegSs = USER_DS;
104 ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 8);
105 ThreadContext.EFlags = (1<<1) + (1<<9);
106
107 /* write lpParameter to highest stack address */
108 *((PBYTE)(BaseAddress + StackSize - 4)) = lpParameter;
109
110 Status = NtCreateThread(&ThreadHandle,
111 THREAD_ALL_ACCESS,
112 &ObjectAttributes,
113 hProcess,
114 &ClientId,
115 &ThreadContext,
116 &InitialTeb,
117 CreateSuspended);
118
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT("NtCreateThread() failed!\n");
122 return NULL;
123 }
124
125 if ( lpThreadId != NULL )
126 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
127
128 return ThreadHandle;
129 }
130
131 NT_TEB *GetTeb(VOID)
132 {
133 return NULL;
134 }
135
136 WINBOOL STDCALL SwitchToThread(VOID)
137 {
138 NTSTATUS errCode;
139 errCode = NtYieldExecution();
140 return TRUE;
141 }
142
143 DWORD STDCALL GetCurrentThreadId()
144 {
145 return((DWORD)(GetTeb()->Cid).UniqueThread);
146 }
147
148 VOID STDCALL ExitThread(UINT uExitCode)
149 {
150 NTSTATUS errCode;
151
152 errCode = NtTerminateThread(NtCurrentThread(),
153 uExitCode);
154 if (!NT_SUCCESS(errCode))
155 {
156 SetLastError(RtlNtStatusToDosError(errCode));
157 }
158 }
159
160 WINBOOL STDCALL GetThreadTimes(HANDLE hThread,
161 LPFILETIME lpCreationTime,
162 LPFILETIME lpExitTime,
163 LPFILETIME lpKernelTime,
164 LPFILETIME lpUserTime)
165 {
166 NTSTATUS errCode;
167 KERNEL_USER_TIMES KernelUserTimes;
168 ULONG ReturnLength;
169
170 errCode = NtQueryInformationThread(hThread,
171 ThreadTimes,
172 &KernelUserTimes,
173 sizeof(KERNEL_USER_TIMES),
174 &ReturnLength);
175 if (!NT_SUCCESS(errCode))
176 {
177 SetLastError(RtlNtStatusToDosError(errCode));
178 return FALSE;
179 }
180 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
181 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
182 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
183 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
184 return TRUE;
185 }
186
187
188 WINBOOL STDCALL GetThreadContext(HANDLE hThread,
189 LPCONTEXT lpContext)
190 {
191 NTSTATUS errCode;
192
193 errCode = NtGetContextThread(hThread,
194 lpContext);
195 if (!NT_SUCCESS(errCode))
196 {
197 SetLastError(RtlNtStatusToDosError(errCode));
198 return FALSE;
199 }
200 return TRUE;
201 }
202
203 WINBOOL STDCALL SetThreadContext(HANDLE hThread,
204 CONST CONTEXT *lpContext)
205 {
206 NTSTATUS errCode;
207
208 errCode = NtSetContextThread(hThread,
209 (void *)lpContext);
210 if (!NT_SUCCESS(errCode))
211 {
212 SetLastError(RtlNtStatusToDosError(errCode));
213 return FALSE;
214 }
215 return TRUE;
216 }
217
218 WINBOOL STDCALL GetExitCodeThread(HANDLE hThread,
219 LPDWORD lpExitCode)
220 {
221 NTSTATUS errCode;
222 THREAD_BASIC_INFORMATION ThreadBasic;
223 ULONG DataWritten;
224
225 errCode = NtQueryInformationThread(hThread,
226 ThreadBasicInformation,
227 &ThreadBasic,
228 sizeof(THREAD_BASIC_INFORMATION),
229 &DataWritten);
230 if (!NT_SUCCESS(errCode))
231 {
232 SetLastError(RtlNtStatusToDosError(errCode));
233 return FALSE;
234 }
235 memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
236 return TRUE;
237 }
238
239 DWORD STDCALL ResumeThread(HANDLE hThread)
240 {
241 NTSTATUS errCode;
242 ULONG PreviousResumeCount;
243
244 errCode = NtResumeThread(hThread,
245 &PreviousResumeCount);
246 if (!NT_SUCCESS(errCode))
247 {
248 SetLastError(RtlNtStatusToDosError(errCode));
249 return -1;
250 }
251 return PreviousResumeCount;
252 }
253
254 DWORD STDCALL SuspendThread(HANDLE hThread)
255 {
256 NTSTATUS errCode;
257 ULONG PreviousSuspendCount;
258
259 errCode = NtSuspendThread(hThread,
260 &PreviousSuspendCount);
261 if (!NT_SUCCESS(errCode))
262 {
263 SetLastError(RtlNtStatusToDosError(errCode));
264 return -1;
265 }
266 return PreviousSuspendCount;
267 }
268
269 DWORD STDCALL SetThreadAffinityMask(HANDLE hThread,
270 DWORD dwThreadAffinityMask)
271 {
272 return 0;
273 }
274
275 WINBOOL STDCALL SetThreadPriority(HANDLE hThread,
276 int nPriority)
277 {
278 NTSTATUS errCode;
279 THREAD_BASIC_INFORMATION ThreadBasic;
280 ULONG DataWritten;
281
282 errCode = NtQueryInformationThread(hThread,
283 ThreadBasicInformation,
284 &ThreadBasic,
285 sizeof(THREAD_BASIC_INFORMATION),
286 &DataWritten);
287 if (!NT_SUCCESS(errCode))
288 {
289 SetLastError(RtlNtStatusToDosError(errCode));
290 return FALSE;
291 }
292 ThreadBasic.BasePriority = nPriority;
293 errCode = NtSetInformationThread(hThread,
294 ThreadBasicInformation,
295 &ThreadBasic,
296 sizeof(THREAD_BASIC_INFORMATION));
297 if (!NT_SUCCESS(errCode))
298 {
299 SetLastError(RtlNtStatusToDosError(errCode));
300 return FALSE;
301 }
302 return TRUE;
303 }
304
305 int STDCALL GetThreadPriority(HANDLE hThread)
306 {
307 NTSTATUS errCode;
308 THREAD_BASIC_INFORMATION ThreadBasic;
309 ULONG DataWritten;
310
311 errCode = NtQueryInformationThread(hThread,
312 ThreadBasicInformation,
313 &ThreadBasic,
314 sizeof(THREAD_BASIC_INFORMATION),
315 &DataWritten);
316 if (!NT_SUCCESS(errCode))
317 {
318 SetLastError(RtlNtStatusToDosError(errCode));
319 return THREAD_PRIORITY_ERROR_RETURN;
320 }
321 return ThreadBasic.BasePriority;
322 }