bb8d88a8eb9042e9c634942bb40ea3cc2ac5f570
[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 #include <internal/i386/segment.h>
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 ULONG BaseAddress;
56
57 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
58 ObjectAttributes.RootDirectory = NULL;
59 ObjectAttributes.ObjectName = NULL;
60 ObjectAttributes.Attributes = 0;
61 if ( lpThreadAttributes != NULL ) {
62 if ( lpThreadAttributes->bInheritHandle )
63 ObjectAttributes.Attributes = OBJ_INHERIT;
64 ObjectAttributes.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
65 }
66 ObjectAttributes.SecurityQualityOfService = NULL;
67
68 if ( ( dwCreationFlags & CREATE_SUSPENDED ) == CREATE_SUSPENDED )
69 CreateSuspended = TRUE;
70 else
71 CreateSuspended = FALSE;
72
73 BaseAddress = 0;
74 ZwAllocateVirtualMemory(hProcess,
75 &BaseAddress,
76 0,
77 &dwStackSize,
78 MEM_COMMIT,
79 PAGE_READWRITE);
80
81
82 memset(&ThreadContext,0,sizeof(CONTEXT));
83 ThreadContext.Eip = lpStartAddress;
84 ThreadContext.SegGs = USER_DS;
85 ThreadContext.SegFs = USER_DS;
86 ThreadContext.SegEs = USER_DS;
87 ThreadContext.SegDs = USER_DS;
88 ThreadContext.SegCs = USER_CS;
89 ThreadContext.SegSs = USER_DS;
90 ThreadContext.Esp = BaseAddress + dwStackSize;
91 ThreadContext.EFlags = (1<<1) + (1<<9);
92
93
94 errCode = NtCreateThread(&ThreadHandle,
95 THREAD_ALL_ACCESS,
96 &ObjectAttributes,
97 hProcess,
98 &ClientId,
99 &ThreadContext,
100 &InitialTeb,
101 CreateSuspended);
102 if ( lpThreadId != NULL )
103 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
104
105 return ThreadHandle;
106 }
107
108 NT_TEB *GetTeb(VOID)
109 {
110 return NULL;
111 }
112
113 WINBOOL STDCALL SwitchToThread(VOID )
114 {
115 NTSTATUS errCode;
116 errCode = NtYieldExecution();
117 return TRUE;
118 }
119
120 DWORD STDCALL GetCurrentThreadId()
121 {
122
123 return (DWORD)(GetTeb()->Cid).UniqueThread;
124 }
125
126 VOID STDCALL ExitThread(UINT uExitCode)
127 {
128 NTSTATUS errCode;
129
130 errCode = NtTerminateThread(
131 NtCurrentThread() ,
132 uExitCode
133 );
134 if ( !NT_SUCCESS(errCode) ) {
135 SetLastError(RtlNtStatusToDosError(errCode));
136 }
137 return;
138 }
139
140 WINBOOL
141 STDCALL
142 GetThreadTimes(
143 HANDLE hThread,
144 LPFILETIME lpCreationTime,
145 LPFILETIME lpExitTime,
146 LPFILETIME lpKernelTime,
147 LPFILETIME lpUserTime
148 )
149 {
150 NTSTATUS errCode;
151 KERNEL_USER_TIMES KernelUserTimes;
152 ULONG ReturnLength;
153 errCode = NtQueryInformationThread(hThread,ThreadTimes,&KernelUserTimes,sizeof(KERNEL_USER_TIMES),&ReturnLength);
154 if ( !NT_SUCCESS(errCode) ) {
155 SetLastError(RtlNtStatusToDosError(errCode));
156 return FALSE;
157 }
158 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
159 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
160 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
161 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
162 return TRUE;
163
164 }
165
166
167 WINBOOL
168 STDCALL GetThreadContext(
169 HANDLE hThread,
170 LPCONTEXT lpContext
171 )
172 {
173 NTSTATUS errCode;
174 errCode = NtGetContextThread(hThread,lpContext);
175 if ( !NT_SUCCESS(errCode) ) {
176 SetLastError(RtlNtStatusToDosError(errCode));
177 return FALSE;
178 }
179 return TRUE;
180 }
181
182 WINBOOL
183 STDCALL
184 SetThreadContext(
185 HANDLE hThread,
186 CONST CONTEXT *lpContext
187 )
188 {
189 NTSTATUS errCode;
190
191 errCode = NtSetContextThread(hThread,(void *)lpContext);
192 if (!NT_SUCCESS(errCode) ) {
193 SetLastError(RtlNtStatusToDosError(errCode));
194 return FALSE;
195 }
196 return TRUE;
197 }
198
199
200
201 WINBOOL
202 STDCALL
203 GetExitCodeThread(
204 HANDLE hThread,
205 LPDWORD lpExitCode
206 )
207 {
208 NTSTATUS errCode;
209 THREAD_BASIC_INFORMATION ThreadBasic;
210 ULONG DataWritten;
211 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
212 if ( !NT_SUCCESS(errCode) ) {
213 SetLastError(RtlNtStatusToDosError(errCode));
214 return FALSE;
215 }
216 memcpy( lpExitCode ,&ThreadBasic.ExitStatus,sizeof(DWORD));
217 return TRUE;
218
219 }
220
221
222 DWORD
223 STDCALL
224 ResumeThread(
225 HANDLE hThread
226 )
227 {
228 NTSTATUS errCode;
229 ULONG PreviousResumeCount;
230
231 errCode = NtResumeThread(hThread,&PreviousResumeCount );
232 if ( !NT_SUCCESS(errCode) ) {
233 SetLastError(RtlNtStatusToDosError(errCode));
234 return -1;
235 }
236 return PreviousResumeCount;
237 }
238
239 DWORD
240 STDCALL
241 SuspendThread(
242 HANDLE hThread
243 )
244 {
245 NTSTATUS errCode;
246 ULONG PreviousSuspendCount;
247
248 errCode = NtSuspendThread(hThread,&PreviousSuspendCount );
249 if ( !NT_SUCCESS(errCode) ) {
250 SetLastError(RtlNtStatusToDosError(errCode));
251 return -1;
252 }
253 return PreviousSuspendCount;
254 }
255
256
257 DWORD
258 STDCALL
259 SetThreadAffinityMask(
260 HANDLE hThread,
261 DWORD dwThreadAffinityMask
262 )
263 {
264 return 0;
265 }
266
267
268 WINBOOL
269 STDCALL
270 SetThreadPriority(
271 HANDLE hThread,
272 int nPriority
273 )
274 {
275 NTSTATUS errCode;
276 THREAD_BASIC_INFORMATION ThreadBasic;
277 ULONG DataWritten;
278 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
279 if ( !NT_SUCCESS(errCode) ) {
280 SetLastError(RtlNtStatusToDosError(errCode));
281 return FALSE;
282 }
283 ThreadBasic.BasePriority = nPriority;
284 errCode = NtSetInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION));
285 if ( !NT_SUCCESS(errCode) ) {
286 SetLastError(RtlNtStatusToDosError(errCode));
287 return FALSE;
288 }
289 return TRUE;
290 }
291
292
293 int
294 STDCALL
295 GetThreadPriority(
296 HANDLE hThread
297 )
298 {
299 NTSTATUS errCode;
300 THREAD_BASIC_INFORMATION ThreadBasic;
301 ULONG DataWritten;
302 errCode = NtQueryInformationThread(hThread,ThreadBasicInformation,&ThreadBasic,sizeof(THREAD_BASIC_INFORMATION),&DataWritten);
303 if ( !NT_SUCCESS(errCode) ) {
304 SetLastError(RtlNtStatusToDosError(errCode));
305 return THREAD_PRIORITY_ERROR_RETURN;
306 }
307 return ThreadBasic.BasePriority;
308 }
309
310
311 /* (WIN32) Thread Local Storage ******************************************** */
312
313 DWORD STDCALL
314 TlsAlloc(VOID)
315 {
316 DWORD dwTlsIndex = GetTeb()->dwTlsIndex;
317
318
319 void **TlsData = GetTeb()->TlsData;
320
321
322 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
323 {
324 TlsData[dwTlsIndex] = NULL;
325 return (dwTlsIndex++);
326 }
327 return (0xFFFFFFFFUL);
328 }
329
330 WINBOOL STDCALL
331 TlsFree(DWORD dwTlsIndex)
332 {
333
334 return (TRUE);
335 }
336
337 LPVOID STDCALL
338 TlsGetValue(DWORD dwTlsIndex)
339 {
340
341
342 void **TlsData = GetTeb()->TlsData;
343
344
345 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
346 {
347
348 SetLastError(NO_ERROR);
349 return (TlsData[dwTlsIndex]);
350 }
351 SetLastError(1);
352 return (NULL);
353 }
354
355 WINBOOL STDCALL
356 TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
357 {
358
359
360 void **TlsData = GetTeb()->TlsData;
361
362
363 if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
364 {
365
366 TlsData[dwTlsIndex] = lpTlsValue;
367 return (TRUE);
368 }
369 return (FALSE);
370 }
371
372 /*************************************************************/