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 *****************************************************************/
27 ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress
,
32 uExitCode
= (lpStartAddress
)(lpParameter
);
34 NtTerminateThread(NtCurrentThread(),
39 HANDLE STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
41 LPTHREAD_START_ROUTINE lpStartAddress
,
43 DWORD dwCreationFlags
,
46 return(CreateRemoteThread(NtCurrentProcess(),
55 HANDLE STDCALL
CreateRemoteThread(HANDLE hProcess
,
56 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
58 LPTHREAD_START_ROUTINE lpStartAddress
,
60 DWORD dwCreationFlags
,
64 OBJECT_ATTRIBUTES ObjectAttributes
;
66 CONTEXT ThreadContext
;
67 INITIAL_TEB InitialTeb
;
68 BOOLEAN CreateSuspended
= FALSE
;
73 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
74 ObjectAttributes
.RootDirectory
= NULL
;
75 ObjectAttributes
.ObjectName
= NULL
;
76 ObjectAttributes
.Attributes
= 0;
77 if (lpThreadAttributes
!= NULL
)
79 if (lpThreadAttributes
->bInheritHandle
)
80 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
81 ObjectAttributes
.SecurityDescriptor
=
82 lpThreadAttributes
->lpSecurityDescriptor
;
84 ObjectAttributes
.SecurityQualityOfService
= NULL
;
86 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
87 CreateSuspended
= TRUE
;
89 CreateSuspended
= FALSE
;
91 StackSize
= (dwStackSize
== 0) ? 4096 : dwStackSize
;
94 Status
= NtAllocateVirtualMemory(hProcess
,
100 if (!NT_SUCCESS(Status
))
102 DPRINT("Could not allocate stack space!\n");
106 DPRINT("Stack base address: %p\n", BaseAddress
);
108 memset(&ThreadContext
,0,sizeof(CONTEXT
));
109 // ThreadContext.Eip = (LONG)lpStartAddress;
110 ThreadContext
.Eip
= (LONG
)ThreadStartup
;
111 ThreadContext
.SegGs
= USER_DS
;
112 ThreadContext
.SegFs
= USER_DS
;
113 ThreadContext
.SegEs
= USER_DS
;
114 ThreadContext
.SegDs
= USER_DS
;
115 ThreadContext
.SegCs
= USER_CS
;
116 ThreadContext
.SegSs
= USER_DS
;
117 ThreadContext
.Esp
= (ULONG
)(BaseAddress
+ StackSize
- 12);
118 ThreadContext
.EFlags
= (1<<1) + (1<<9);
120 /* initialize call stack */
121 *((PULONG
)(BaseAddress
+ StackSize
- 4)) = (ULONG
)lpParameter
;
122 *((PULONG
)(BaseAddress
+ StackSize
- 8)) = (ULONG
)lpStartAddress
;
123 *((PULONG
)(BaseAddress
+ StackSize
- 12)) = 0xdeadbeef;
125 DPRINT("Esp: %p\n", ThreadContext
.Esp
);
126 DPRINT("Eip: %p\n", ThreadContext
.Eip
);
128 Status
= NtCreateThread(&ThreadHandle
,
137 if (!NT_SUCCESS(Status
))
139 DPRINT("NtCreateThread() failed!\n");
143 if ( lpThreadId
!= NULL
)
144 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
154 WINBOOL STDCALL
SwitchToThread(VOID
)
157 errCode
= NtYieldExecution();
161 DWORD STDCALL
GetCurrentThreadId()
163 return((DWORD
)(GetTeb()->Cid
).UniqueThread
);
166 VOID STDCALL
ExitThread(UINT uExitCode
)
170 errCode
= NtTerminateThread(NtCurrentThread(),
172 if (!NT_SUCCESS(errCode
))
174 SetLastError(RtlNtStatusToDosError(errCode
));
178 WINBOOL STDCALL
GetThreadTimes(HANDLE hThread
,
179 LPFILETIME lpCreationTime
,
180 LPFILETIME lpExitTime
,
181 LPFILETIME lpKernelTime
,
182 LPFILETIME lpUserTime
)
185 KERNEL_USER_TIMES KernelUserTimes
;
188 errCode
= NtQueryInformationThread(hThread
,
191 sizeof(KERNEL_USER_TIMES
),
193 if (!NT_SUCCESS(errCode
))
195 SetLastError(RtlNtStatusToDosError(errCode
));
198 memcpy(lpCreationTime
, &KernelUserTimes
.CreateTime
, sizeof(FILETIME
));
199 memcpy(lpExitTime
, &KernelUserTimes
.ExitTime
, sizeof(FILETIME
));
200 memcpy(lpKernelTime
, &KernelUserTimes
.KernelTime
, sizeof(FILETIME
));
201 memcpy(lpUserTime
, &KernelUserTimes
.UserTime
, sizeof(FILETIME
));
206 WINBOOL STDCALL
GetThreadContext(HANDLE hThread
,
211 errCode
= NtGetContextThread(hThread
,
213 if (!NT_SUCCESS(errCode
))
215 SetLastError(RtlNtStatusToDosError(errCode
));
221 WINBOOL STDCALL
SetThreadContext(HANDLE hThread
,
222 CONST CONTEXT
*lpContext
)
226 errCode
= NtSetContextThread(hThread
,
228 if (!NT_SUCCESS(errCode
))
230 SetLastError(RtlNtStatusToDosError(errCode
));
236 WINBOOL STDCALL
GetExitCodeThread(HANDLE hThread
,
240 THREAD_BASIC_INFORMATION ThreadBasic
;
243 errCode
= NtQueryInformationThread(hThread
,
244 ThreadBasicInformation
,
246 sizeof(THREAD_BASIC_INFORMATION
),
248 if (!NT_SUCCESS(errCode
))
250 SetLastError(RtlNtStatusToDosError(errCode
));
253 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
257 DWORD STDCALL
ResumeThread(HANDLE hThread
)
260 ULONG PreviousResumeCount
;
262 errCode
= NtResumeThread(hThread
,
263 &PreviousResumeCount
);
264 if (!NT_SUCCESS(errCode
))
266 SetLastError(RtlNtStatusToDosError(errCode
));
269 return PreviousResumeCount
;
282 errCode
= NtTerminateThread(hThread
,
284 if (!NT_SUCCESS(errCode
))
286 SetLastError(RtlNtStatusToDosError(errCode
));
293 DWORD STDCALL
SuspendThread(HANDLE hThread
)
296 ULONG PreviousSuspendCount
;
298 errCode
= NtSuspendThread(hThread
,
299 &PreviousSuspendCount
);
300 if (!NT_SUCCESS(errCode
))
302 SetLastError(RtlNtStatusToDosError(errCode
));
305 return PreviousSuspendCount
;
308 DWORD STDCALL
SetThreadAffinityMask(HANDLE hThread
,
309 DWORD dwThreadAffinityMask
)
314 WINBOOL STDCALL
SetThreadPriority(HANDLE hThread
,
318 THREAD_BASIC_INFORMATION ThreadBasic
;
321 errCode
= NtQueryInformationThread(hThread
,
322 ThreadBasicInformation
,
324 sizeof(THREAD_BASIC_INFORMATION
),
326 if (!NT_SUCCESS(errCode
))
328 SetLastError(RtlNtStatusToDosError(errCode
));
331 ThreadBasic
.BasePriority
= nPriority
;
332 errCode
= NtSetInformationThread(hThread
,
333 ThreadBasicInformation
,
335 sizeof(THREAD_BASIC_INFORMATION
));
336 if (!NT_SUCCESS(errCode
))
338 SetLastError(RtlNtStatusToDosError(errCode
));
344 int STDCALL
GetThreadPriority(HANDLE hThread
)
347 THREAD_BASIC_INFORMATION ThreadBasic
;
350 errCode
= NtQueryInformationThread(hThread
,
351 ThreadBasicInformation
,
353 sizeof(THREAD_BASIC_INFORMATION
),
355 if (!NT_SUCCESS(errCode
))
357 SetLastError(RtlNtStatusToDosError(errCode
));
358 return THREAD_PRIORITY_ERROR_RETURN
;
360 return ThreadBasic
.BasePriority
;