1 /* $Id: thread.c,v 1.14 2000/04/14 01:48:26 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>
19 #include <internal/i386/segment.h>
22 #include <kernel32/kernel32.h>
25 /* FUNCTIONS *****************************************************************/
28 ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress
,
33 uExitCode
= (lpStartAddress
)(lpParameter
);
35 NtTerminateThread(NtCurrentThread(),
40 HANDLE STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
42 LPTHREAD_START_ROUTINE lpStartAddress
,
44 DWORD dwCreationFlags
,
47 return(CreateRemoteThread(NtCurrentProcess(),
56 HANDLE STDCALL
CreateRemoteThread(HANDLE hProcess
,
57 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
59 LPTHREAD_START_ROUTINE lpStartAddress
,
61 DWORD dwCreationFlags
,
65 OBJECT_ATTRIBUTES ObjectAttributes
;
67 CONTEXT ThreadContext
;
68 INITIAL_TEB InitialTeb
;
69 BOOLEAN CreateSuspended
= FALSE
;
74 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
75 ObjectAttributes
.RootDirectory
= NULL
;
76 ObjectAttributes
.ObjectName
= NULL
;
77 ObjectAttributes
.Attributes
= 0;
78 if (lpThreadAttributes
!= NULL
)
80 if (lpThreadAttributes
->bInheritHandle
)
81 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
82 ObjectAttributes
.SecurityDescriptor
=
83 lpThreadAttributes
->lpSecurityDescriptor
;
85 ObjectAttributes
.SecurityQualityOfService
= NULL
;
87 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
88 CreateSuspended
= TRUE
;
90 CreateSuspended
= FALSE
;
92 StackSize
= (dwStackSize
== 0) ? 4096 : dwStackSize
;
96 Status
= NtAllocateVirtualMemory(hProcess
,
102 if (!NT_SUCCESS(Status
))
104 DPRINT("Could not allocate stack space!\n");
109 DPRINT("Stack base address: %p\n", BaseAddress
);
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);
122 /* initialize call stack */
123 *((PULONG
)(BaseAddress
+ StackSize
- 4)) = (ULONG
)lpParameter
;
124 *((PULONG
)(BaseAddress
+ StackSize
- 8)) = (ULONG
)lpStartAddress
;
125 *((PULONG
)(BaseAddress
+ StackSize
- 12)) = 0xdeadbeef;
127 DPRINT("Esp: %p\n", ThreadContext
.Esp
);
128 DPRINT("Eip: %p\n", ThreadContext
.Eip
);
130 Status
= NtCreateThread(&ThreadHandle
,
139 if (!NT_SUCCESS(Status
))
141 DPRINT("NtCreateThread() failed!\n");
145 if ( lpThreadId
!= NULL
)
146 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
153 return NtCurrentTeb();
156 WINBOOL STDCALL
SwitchToThread(VOID
)
159 errCode
= NtYieldExecution();
163 DWORD STDCALL
GetCurrentThreadId()
165 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
168 VOID STDCALL
ExitThread(UINT uExitCode
)
172 errCode
= NtTerminateThread(NtCurrentThread(),
174 if (!NT_SUCCESS(errCode
))
176 SetLastError(RtlNtStatusToDosError(errCode
));
180 WINBOOL STDCALL
GetThreadTimes(HANDLE hThread
,
181 LPFILETIME lpCreationTime
,
182 LPFILETIME lpExitTime
,
183 LPFILETIME lpKernelTime
,
184 LPFILETIME lpUserTime
)
187 KERNEL_USER_TIMES KernelUserTimes
;
190 errCode
= NtQueryInformationThread(hThread
,
193 sizeof(KERNEL_USER_TIMES
),
195 if (!NT_SUCCESS(errCode
))
197 SetLastError(RtlNtStatusToDosError(errCode
));
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
));
208 WINBOOL STDCALL
GetThreadContext(HANDLE hThread
,
213 errCode
= NtGetContextThread(hThread
,
215 if (!NT_SUCCESS(errCode
))
217 SetLastError(RtlNtStatusToDosError(errCode
));
223 WINBOOL STDCALL
SetThreadContext(HANDLE hThread
,
224 CONST CONTEXT
*lpContext
)
228 errCode
= NtSetContextThread(hThread
,
230 if (!NT_SUCCESS(errCode
))
232 SetLastError(RtlNtStatusToDosError(errCode
));
238 WINBOOL STDCALL
GetExitCodeThread(HANDLE hThread
,
242 THREAD_BASIC_INFORMATION ThreadBasic
;
245 errCode
= NtQueryInformationThread(hThread
,
246 ThreadBasicInformation
,
248 sizeof(THREAD_BASIC_INFORMATION
),
250 if (!NT_SUCCESS(errCode
))
252 SetLastError(RtlNtStatusToDosError(errCode
));
255 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
259 DWORD STDCALL
ResumeThread(HANDLE hThread
)
262 ULONG PreviousResumeCount
;
264 errCode
= NtResumeThread(hThread
,
265 &PreviousResumeCount
);
266 if (!NT_SUCCESS(errCode
))
268 SetLastError(RtlNtStatusToDosError(errCode
));
271 return PreviousResumeCount
;
284 errCode
= NtTerminateThread(hThread
,
286 if (!NT_SUCCESS(errCode
))
288 SetLastError(RtlNtStatusToDosError(errCode
));
295 DWORD STDCALL
SuspendThread(HANDLE hThread
)
298 ULONG PreviousSuspendCount
;
300 errCode
= NtSuspendThread(hThread
,
301 &PreviousSuspendCount
);
302 if (!NT_SUCCESS(errCode
))
304 SetLastError(RtlNtStatusToDosError(errCode
));
307 return PreviousSuspendCount
;
310 DWORD STDCALL
SetThreadAffinityMask(HANDLE hThread
,
311 DWORD dwThreadAffinityMask
)
316 WINBOOL STDCALL
SetThreadPriority(HANDLE hThread
,
320 THREAD_BASIC_INFORMATION ThreadBasic
;
323 errCode
= NtQueryInformationThread(hThread
,
324 ThreadBasicInformation
,
326 sizeof(THREAD_BASIC_INFORMATION
),
328 if (!NT_SUCCESS(errCode
))
330 SetLastError(RtlNtStatusToDosError(errCode
));
333 ThreadBasic
.BasePriority
= nPriority
;
334 errCode
= NtSetInformationThread(hThread
,
335 ThreadBasicInformation
,
337 sizeof(THREAD_BASIC_INFORMATION
));
338 if (!NT_SUCCESS(errCode
))
340 SetLastError(RtlNtStatusToDosError(errCode
));
346 int STDCALL
GetThreadPriority(HANDLE hThread
)
349 THREAD_BASIC_INFORMATION ThreadBasic
;
352 errCode
= NtQueryInformationThread(hThread
,
353 ThreadBasicInformation
,
355 sizeof(THREAD_BASIC_INFORMATION
),
357 if (!NT_SUCCESS(errCode
))
359 SetLastError(RtlNtStatusToDosError(errCode
));
360 return THREAD_PRIORITY_ERROR_RETURN
;
362 return ThreadBasic
.BasePriority
;