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