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
12 /* INCLUDES ******************************************************************/
15 #include <kernel32/thread.h>
16 #include <ddk/ntddk.h>
18 #include <internal/i386/segment.h>
21 #include <kernel32/kernel32.h>
24 /* FUNCTIONS *****************************************************************/
26 HANDLE STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
28 LPTHREAD_START_ROUTINE lpStartAddress
,
30 DWORD dwCreationFlags
,
33 return(CreateRemoteThread(NtCurrentProcess(),
42 HANDLE STDCALL
CreateRemoteThread(HANDLE hProcess
,
43 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
45 LPTHREAD_START_ROUTINE lpStartAddress
,
47 DWORD dwCreationFlags
,
51 OBJECT_ATTRIBUTES ObjectAttributes
;
53 CONTEXT ThreadContext
;
54 INITIAL_TEB InitialTeb
;
55 BOOLEAN CreateSuspended
= FALSE
;
61 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
62 ObjectAttributes
.RootDirectory
= NULL
;
63 ObjectAttributes
.ObjectName
= NULL
;
64 ObjectAttributes
.Attributes
= 0;
65 if (lpThreadAttributes
!= NULL
)
67 if (lpThreadAttributes
->bInheritHandle
)
68 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
69 ObjectAttributes
.SecurityDescriptor
=
70 lpThreadAttributes
->lpSecurityDescriptor
;
72 ObjectAttributes
.SecurityQualityOfService
= NULL
;
74 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
75 CreateSuspended
= TRUE
;
77 CreateSuspended
= FALSE
;
79 StackSize
= (dwStackSize
== 0) ? 4096 : dwStackSize
;
82 Status
= NtAllocateVirtualMemory(hProcess
,
88 if (!NT_SUCCESS(Status
))
90 DPRINT("Could not allocate stack space!\n");
94 DPRINT("Stack base address: %p\n", BaseAddress
);
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);
107 /* write lpParameter to highest stack address */
108 *((PBYTE
)(BaseAddress
+ StackSize
- 4)) = lpParameter
;
110 Status
= NtCreateThread(&ThreadHandle
,
119 if (!NT_SUCCESS(Status
))
121 DPRINT("NtCreateThread() failed!\n");
125 if ( lpThreadId
!= NULL
)
126 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
136 WINBOOL STDCALL
SwitchToThread(VOID
)
139 errCode
= NtYieldExecution();
143 DWORD STDCALL
GetCurrentThreadId()
145 return((DWORD
)(GetTeb()->Cid
).UniqueThread
);
148 VOID STDCALL
ExitThread(UINT uExitCode
)
152 errCode
= NtTerminateThread(NtCurrentThread(),
154 if (!NT_SUCCESS(errCode
))
156 SetLastError(RtlNtStatusToDosError(errCode
));
160 WINBOOL STDCALL
GetThreadTimes(HANDLE hThread
,
161 LPFILETIME lpCreationTime
,
162 LPFILETIME lpExitTime
,
163 LPFILETIME lpKernelTime
,
164 LPFILETIME lpUserTime
)
167 KERNEL_USER_TIMES KernelUserTimes
;
170 errCode
= NtQueryInformationThread(hThread
,
173 sizeof(KERNEL_USER_TIMES
),
175 if (!NT_SUCCESS(errCode
))
177 SetLastError(RtlNtStatusToDosError(errCode
));
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
));
188 WINBOOL STDCALL
GetThreadContext(HANDLE hThread
,
193 errCode
= NtGetContextThread(hThread
,
195 if (!NT_SUCCESS(errCode
))
197 SetLastError(RtlNtStatusToDosError(errCode
));
203 WINBOOL STDCALL
SetThreadContext(HANDLE hThread
,
204 CONST CONTEXT
*lpContext
)
208 errCode
= NtSetContextThread(hThread
,
210 if (!NT_SUCCESS(errCode
))
212 SetLastError(RtlNtStatusToDosError(errCode
));
218 WINBOOL STDCALL
GetExitCodeThread(HANDLE hThread
,
222 THREAD_BASIC_INFORMATION ThreadBasic
;
225 errCode
= NtQueryInformationThread(hThread
,
226 ThreadBasicInformation
,
228 sizeof(THREAD_BASIC_INFORMATION
),
230 if (!NT_SUCCESS(errCode
))
232 SetLastError(RtlNtStatusToDosError(errCode
));
235 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
239 DWORD STDCALL
ResumeThread(HANDLE hThread
)
242 ULONG PreviousResumeCount
;
244 errCode
= NtResumeThread(hThread
,
245 &PreviousResumeCount
);
246 if (!NT_SUCCESS(errCode
))
248 SetLastError(RtlNtStatusToDosError(errCode
));
251 return PreviousResumeCount
;
254 DWORD STDCALL
SuspendThread(HANDLE hThread
)
257 ULONG PreviousSuspendCount
;
259 errCode
= NtSuspendThread(hThread
,
260 &PreviousSuspendCount
);
261 if (!NT_SUCCESS(errCode
))
263 SetLastError(RtlNtStatusToDosError(errCode
));
266 return PreviousSuspendCount
;
269 DWORD STDCALL
SetThreadAffinityMask(HANDLE hThread
,
270 DWORD dwThreadAffinityMask
)
275 WINBOOL STDCALL
SetThreadPriority(HANDLE hThread
,
279 THREAD_BASIC_INFORMATION ThreadBasic
;
282 errCode
= NtQueryInformationThread(hThread
,
283 ThreadBasicInformation
,
285 sizeof(THREAD_BASIC_INFORMATION
),
287 if (!NT_SUCCESS(errCode
))
289 SetLastError(RtlNtStatusToDosError(errCode
));
292 ThreadBasic
.BasePriority
= nPriority
;
293 errCode
= NtSetInformationThread(hThread
,
294 ThreadBasicInformation
,
296 sizeof(THREAD_BASIC_INFORMATION
));
297 if (!NT_SUCCESS(errCode
))
299 SetLastError(RtlNtStatusToDosError(errCode
));
305 int STDCALL
GetThreadPriority(HANDLE hThread
)
308 THREAD_BASIC_INFORMATION ThreadBasic
;
311 errCode
= NtQueryInformationThread(hThread
,
312 ThreadBasicInformation
,
314 sizeof(THREAD_BASIC_INFORMATION
),
316 if (!NT_SUCCESS(errCode
))
318 SetLastError(RtlNtStatusToDosError(errCode
));
319 return THREAD_PRIORITY_ERROR_RETURN
;
321 return ThreadBasic
.BasePriority
;