1 /* $Id: thread.c,v 1.18 2000/09/01 17:09:50 ekohl Exp $
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
13 /* INCLUDES ******************************************************************/
15 #include <ddk/ntddk.h>
17 #include <kernel32/thread.h>
18 #include <ntdll/ldr.h>
20 #include <napi/i386/segment.h>
23 #include <kernel32/kernel32.h>
24 #include <kernel32/error.h>
27 /* FUNCTIONS *****************************************************************/
30 ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress
,
35 uExitCode
= (lpStartAddress
)(lpParameter
);
37 NtTerminateThread(NtCurrentThread(),
42 HANDLE STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
44 LPTHREAD_START_ROUTINE lpStartAddress
,
46 DWORD dwCreationFlags
,
49 return(CreateRemoteThread(NtCurrentProcess(),
58 HANDLE STDCALL
CreateRemoteThread(HANDLE hProcess
,
59 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
61 LPTHREAD_START_ROUTINE lpStartAddress
,
63 DWORD dwCreationFlags
,
67 OBJECT_ATTRIBUTES ObjectAttributes
;
69 CONTEXT ThreadContext
;
70 INITIAL_TEB InitialTeb
;
71 BOOLEAN CreateSuspended
= FALSE
;
76 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
77 ObjectAttributes
.RootDirectory
= NULL
;
78 ObjectAttributes
.ObjectName
= NULL
;
79 ObjectAttributes
.Attributes
= 0;
80 if (lpThreadAttributes
!= NULL
)
82 if (lpThreadAttributes
->bInheritHandle
)
83 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
84 ObjectAttributes
.SecurityDescriptor
=
85 lpThreadAttributes
->lpSecurityDescriptor
;
87 ObjectAttributes
.SecurityQualityOfService
= NULL
;
89 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
90 CreateSuspended
= TRUE
;
92 CreateSuspended
= FALSE
;
94 StackSize
= (dwStackSize
== 0) ? 4096 : dwStackSize
;
98 Status
= NtAllocateVirtualMemory(hProcess
,
104 if (!NT_SUCCESS(Status
))
106 DPRINT("Could not allocate stack space!\n");
111 DPRINT("Stack base address: %p\n", BaseAddress
);
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);
124 /* initialize call stack */
125 *((PULONG
)(BaseAddress
+ StackSize
- 4)) = (ULONG
)lpParameter
;
126 *((PULONG
)(BaseAddress
+ StackSize
- 8)) = (ULONG
)lpStartAddress
;
127 *((PULONG
)(BaseAddress
+ StackSize
- 12)) = 0xdeadbeef;
129 DPRINT("Esp: %p\n", ThreadContext
.Esp
);
130 DPRINT("Eip: %p\n", ThreadContext
.Eip
);
132 Status
= NtCreateThread(&ThreadHandle
,
141 if (!NT_SUCCESS(Status
))
143 DPRINT("NtCreateThread() failed!\n");
147 if ( lpThreadId
!= NULL
)
148 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
155 return NtCurrentTeb();
158 WINBOOL STDCALL
SwitchToThread(VOID
)
161 errCode
= NtYieldExecution();
165 DWORD STDCALL
GetCurrentThreadId()
167 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
170 VOID STDCALL
ExitThread(UINT uExitCode
)
174 errCode
= NtTerminateThread(NtCurrentThread(),
176 if (!NT_SUCCESS(errCode
))
178 SetLastErrorByStatus(errCode
);
182 WINBOOL STDCALL
GetThreadTimes(HANDLE hThread
,
183 LPFILETIME lpCreationTime
,
184 LPFILETIME lpExitTime
,
185 LPFILETIME lpKernelTime
,
186 LPFILETIME lpUserTime
)
189 KERNEL_USER_TIMES KernelUserTimes
;
192 errCode
= NtQueryInformationThread(hThread
,
195 sizeof(KERNEL_USER_TIMES
),
197 if (!NT_SUCCESS(errCode
))
199 SetLastErrorByStatus(errCode
);
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
));
210 WINBOOL STDCALL
GetThreadContext(HANDLE hThread
,
215 errCode
= NtGetContextThread(hThread
,
217 if (!NT_SUCCESS(errCode
))
219 SetLastErrorByStatus(errCode
);
225 WINBOOL STDCALL
SetThreadContext(HANDLE hThread
,
226 CONST CONTEXT
*lpContext
)
230 errCode
= NtSetContextThread(hThread
,
232 if (!NT_SUCCESS(errCode
))
234 SetLastErrorByStatus(errCode
);
240 WINBOOL STDCALL
GetExitCodeThread(HANDLE hThread
,
244 THREAD_BASIC_INFORMATION ThreadBasic
;
247 errCode
= NtQueryInformationThread(hThread
,
248 ThreadBasicInformation
,
250 sizeof(THREAD_BASIC_INFORMATION
),
252 if (!NT_SUCCESS(errCode
))
254 SetLastErrorByStatus(errCode
);
257 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
261 DWORD STDCALL
ResumeThread(HANDLE hThread
)
264 ULONG PreviousResumeCount
;
266 errCode
= NtResumeThread(hThread
,
267 &PreviousResumeCount
);
268 if (!NT_SUCCESS(errCode
))
270 SetLastErrorByStatus(errCode
);
273 return PreviousResumeCount
;
286 errCode
= NtTerminateThread(hThread
,
288 if (!NT_SUCCESS(errCode
))
290 SetLastErrorByStatus(errCode
);
297 DWORD STDCALL
SuspendThread(HANDLE hThread
)
300 ULONG PreviousSuspendCount
;
302 errCode
= NtSuspendThread(hThread
,
303 &PreviousSuspendCount
);
304 if (!NT_SUCCESS(errCode
))
306 SetLastErrorByStatus(errCode
);
309 return PreviousSuspendCount
;
312 DWORD STDCALL
SetThreadAffinityMask(HANDLE hThread
,
313 DWORD dwThreadAffinityMask
)
318 WINBOOL STDCALL
SetThreadPriority(HANDLE hThread
,
322 THREAD_BASIC_INFORMATION ThreadBasic
;
325 errCode
= NtQueryInformationThread(hThread
,
326 ThreadBasicInformation
,
328 sizeof(THREAD_BASIC_INFORMATION
),
330 if (!NT_SUCCESS(errCode
))
332 SetLastErrorByStatus(errCode
);
335 ThreadBasic
.BasePriority
= nPriority
;
336 errCode
= NtSetInformationThread(hThread
,
337 ThreadBasicInformation
,
339 sizeof(THREAD_BASIC_INFORMATION
));
340 if (!NT_SUCCESS(errCode
))
342 SetLastErrorByStatus(errCode
);
348 int STDCALL
GetThreadPriority(HANDLE hThread
)
351 THREAD_BASIC_INFORMATION ThreadBasic
;
354 errCode
= NtQueryInformationThread(hThread
,
355 ThreadBasicInformation
,
357 sizeof(THREAD_BASIC_INFORMATION
),
359 if (!NT_SUCCESS(errCode
))
361 SetLastErrorByStatus(errCode
);
362 return THREAD_PRIORITY_ERROR_RETURN
;
364 return ThreadBasic
.BasePriority
;