Rolled in various changes from others
[reactos.git] / reactos / lib / kernel32 / thread / thread.c
1 /*
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
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 #include <windows.h>
13 #include <kernel32/thread.h>
14 #include <ddk/ntddk.h>
15 #include <string.h>
16
17
18 HANDLE
19 STDCALL
20 CreateThread(
21 LPSECURITY_ATTRIBUTES lpThreadAttributes,
22 DWORD dwStackSize,
23 LPTHREAD_START_ROUTINE lpStartAddress,
24 LPVOID lpParameter,
25 DWORD dwCreationFlags,
26 LPDWORD lpThreadId
27 )
28 {
29 return CreateRemoteThread(NtCurrentProcess(),lpThreadAttributes,dwStackSize,
30 lpStartAddress,lpParameter,dwCreationFlags,lpThreadId);
31 }
32
33
34
35
36 HANDLE
37 STDCALL
38 CreateRemoteThread(
39 HANDLE hProcess,
40 LPSECURITY_ATTRIBUTES lpThreadAttributes,
41 DWORD dwStackSize,
42 LPTHREAD_START_ROUTINE lpStartAddress,
43 LPVOID lpParameter,
44 DWORD dwCreationFlags,
45 LPDWORD lpThreadId
46 )
47 {
48 NTSTATUS errCode;
49 HANDLE ThreadHandle;
50 OBJECT_ATTRIBUTES ObjectAttributes;
51 CLIENT_ID ClientId;
52 CONTEXT ThreadContext;
53 INITIAL_TEB InitialTeb;
54 BOOLEAN CreateSuspended = FALSE;
55
56 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
57 ObjectAttributes.RootDirectory = NULL;
58 ObjectAttributes.ObjectName = NULL;
59 ObjectAttributes.Attributes = 0;
60 if ( lpThreadAttributes != NULL ) {
61 if ( lpThreadAttributes->bInheritHandle )
62 ObjectAttributes.Attributes = OBJ_INHERIT;
63 ObjectAttributes.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
64 }
65 ObjectAttributes.SecurityQualityOfService = NULL;
66
67 if ( ( dwCreationFlags & CREATE_SUSPENDED ) == CREATE_SUSPENDED )
68 CreateSuspended = TRUE;
69 else
70 CreateSuspended = FALSE;
71 // fix context
72 GetThreadContext(NtCurrentThread(),&ThreadContext);
73 // fix teb [ stack context ] --> check the image file
74
75 errCode = NtCreateThread(
76 &ThreadHandle,
77 THREAD_ALL_ACCESS,
78 &ObjectAttributes,
79 hProcess,
80 &ClientId,
81 &ThreadContext,
82 &InitialTeb,
83 CreateSuspended
84 );
85 if ( lpThreadId != NULL )
86 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
87
88 return ThreadHandle;
89 }
90
91 NT_TEB *GetTeb(VOID)
92 {
93 return NULL;
94 }
95
96 WINBOOL STDCALL
97 SwitchToThread(VOID )
98 {
99 NTSTATUS errCode;
100 errCode = NtYieldExecution();
101 return TRUE;
102 }
103
104 DWORD
105 STDCALL
106 GetCurrentThreadId()
107 {
108
109 return (DWORD)(GetTeb()->Cid).UniqueThread;
110 }
111
112 VOID
113 STDCALL
114 ExitThread(
115 UINT uExitCode
116 )
117 {
118 NTSTATUS errCode;
119
120 errCode = NtTerminateThread(
121 NtCurrentThread() ,
122 uExitCode
123 );
124 if ( !NT_SUCCESS(errCode) ) {
125 SetLastError(RtlNtStatusToDosError(errCode));
126 }
127 return;
128 }
129
130 WINBOOL
131 STDCALL
132 GetThreadTimes(
133 HANDLE hThread,
134 LPFILETIME lpCreationTime,
135 LPFILETIME lpExitTime,
136 LPFILETIME lpKernelTime,
137 LPFILETIME lpUserTime
138 )
139 {
140 NTSTATUS errCode;
141 KERNEL_USER_TIMES KernelUserTimes;
142 ULONG ReturnLength;
143 errCode = NtQueryInformationThread(hThread,ThreadTimes,&KernelUserTimes,sizeof(KERNEL_USER_TIMES),&ReturnLength);
144 if ( !NT_SUCCESS(errCode) ) {
145 SetLastError(RtlNtStatusToDosError(errCode));
146 return FALSE;
147 }
148 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
149 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
150 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
151 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
152 return TRUE;
153
154 }
155
156
157 WINBOOL
158 STDCALL GetThreadContext(
159 HANDLE hThread,
160 LPCONTEXT lpContext
161 )
162 {
163 NTSTATUS errCode;
164 errCode = NtGetContextThread(hThread,lpContext);
165 if ( !NT_SUCCESS(errCode) ) {
166 SetLastError(RtlNtStatusToDosError(errCode));
167 return FALSE;
168 }
169 return TRUE;
170 }
171
172 WINBOOL
173 STDCALL
174 SetThreadContext(
175 HANDLE hThread,
176 CONST CONTEXT *lpContext
177 )
178 {
179 NTSTATUS errCode;
180
181 errCode = NtSetContextThread(hThread,(void *)lpContext);
182 if (!NT_SUCCESS(errCode) ) {
183 SetLastError(RtlNtStatusToDosError(errCode));
184 return FALSE;
185 }
186 return TRUE;
187 }
188
189
190
191 WINBOOL
192 STDCALL
193 GetExitCodeThread(
194 HANDLE hThread,
195 LPDWORD lpExitCode
196 )
197 {
198 NTSTATUS errCode;
199 THREAD_BASIC_INFORMATION ThreadBasic;
200 ULONG DataWritten;
201 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
202 if ( !NT_SUCCESS(errCode) ) {
203 SetLastError(RtlNtStatusToDosError(errCode));
204 return FALSE;
205 }
206 memcpy( lpExitCode ,&ThreadBasic.ExitStatus,sizeof(DWORD));
207 return TRUE;
208
209 }
210
211
212 DWORD
213 STDCALL
214 ResumeThread(
215 HANDLE hThread
216 )
217 {
218 NTSTATUS errCode;
219 ULONG PreviousResumeCount;
220
221 errCode = NtResumeThread(hThread,&PreviousResumeCount );
222 if ( !NT_SUCCESS(errCode) ) {
223 SetLastError(RtlNtStatusToDosError(errCode));
224 return -1;
225 }
226 return PreviousResumeCount;
227 }
228
229 DWORD
230 STDCALL
231 SuspendThread(
232 HANDLE hThread
233 )
234 {
235 NTSTATUS errCode;
236 ULONG PreviousSuspendCount;
237
238 errCode = NtSuspendThread(hThread,&PreviousSuspendCount );
239 if ( !NT_SUCCESS(errCode) ) {
240 SetLastError(RtlNtStatusToDosError(errCode));
241 return -1;
242 }
243 return PreviousSuspendCount;
244 }
245
246
247 DWORD
248 STDCALL
249 SetThreadAffinityMask(
250 HANDLE hThread,
251 DWORD dwThreadAffinityMask
252 )
253 {
254 return 0;
255 }
256
257
258 WINBOOL
259 STDCALL
260 SetThreadPriority(
261 HANDLE hThread,
262 int nPriority
263 )
264 {
265 NTSTATUS errCode;
266 THREAD_BASIC_INFORMATION ThreadBasic;
267 ULONG DataWritten;
268 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
269 if ( !NT_SUCCESS(errCode) ) {
270 SetLastError(RtlNtStatusToDosError(errCode));
271 return FALSE;
272 }
273 ThreadBasic.BasePriority = nPriority;
274 errCode = NtSetInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION));
275 if ( !NT_SUCCESS(errCode) ) {
276 SetLastError(RtlNtStatusToDosError(errCode));
277 return FALSE;
278 }
279 return TRUE;
280 }
281
282
283 int
284 STDCALL
285 GetThreadPriority(
286 HANDLE hThread
287 )
288 {
289 NTSTATUS errCode;
290 THREAD_BASIC_INFORMATION ThreadBasic;
291 ULONG DataWritten;
292 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
293 if ( !NT_SUCCESS(errCode) ) {
294 SetLastError(RtlNtStatusToDosError(errCode));
295 return THREAD_PRIORITY_ERROR_RETURN;
296 }
297 return ThreadBasic.BasePriority;
298 }
299
300
301 /* (WIN32) Thread Local Storage ******************************************** */
302
303 DWORD STDCALL
304 TlsAlloc(VOID)
305 {
306 DWORD dwTlsIndex = GetTeb()->dwTlsIndex;
307
308
309 void **TlsData = GetTeb()->TlsData;
310
311
312 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
313 {
314 TlsData[dwTlsIndex] = NULL;
315 return (dwTlsIndex++);
316 }
317 return (0xFFFFFFFFUL);
318 }
319
320 WINBOOL STDCALL
321 TlsFree(DWORD dwTlsIndex)
322 {
323
324 return (TRUE);
325 }
326
327 LPVOID STDCALL
328 TlsGetValue(DWORD dwTlsIndex)
329 {
330
331
332 void **TlsData = GetTeb()->TlsData;
333
334
335 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
336 {
337
338 SetLastError(NO_ERROR);
339 return (TlsData[dwTlsIndex]);
340 }
341 SetLastError(1);
342 return (NULL);
343 }
344
345 WINBOOL STDCALL
346 TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
347 {
348
349
350 void **TlsData = GetTeb()->TlsData;
351
352
353 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
354 {
355
356 TlsData[dwTlsIndex] = lpTlsValue;
357 return (TRUE);
358 }
359 return (FALSE);
360 }
361
362 /*************************************************************/