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