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 ******************************************************************/
16 #include <kernel32/thread.h>
17 #include <ntdll/ldr.h>
19 #include <napi/i386/segment.h>
22 #include <kernel32/kernel32.h>
23 #include <kernel32/error.h>
26 static VOID ThreadAttachDlls (VOID);
28 /* FUNCTIONS *****************************************************************/
31 EXCEPTION_DISPOSITION
\r
34 struct _EXCEPTION_RECORD *ExceptionRecord,
\r
35 void * EstablisherFrame,
\r
36 struct _CONTEXT *ContextRecord,
\r
37 void * DispatcherContext )
\r
41 /* We should not get to here */
42 return ExceptionContinueSearch;
46 ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
51 __try1(_except_handler)
53 /* FIXME: notify csrss of thread creation ?? */
54 uExitCode = (lpStartAddress)(lpParameter);
59 ExitThread(uExitCode);
62 HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
64 LPTHREAD_START_ROUTINE lpStartAddress,
66 DWORD dwCreationFlags,
69 return(CreateRemoteThread(NtCurrentProcess(),
78 HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
79 LPSECURITY_ATTRIBUTES lpThreadAttributes,
81 LPTHREAD_START_ROUTINE lpStartAddress,
83 DWORD dwCreationFlags,
87 OBJECT_ATTRIBUTES ObjectAttributes;
89 CONTEXT ThreadContext;
90 INITIAL_TEB InitialTeb;
91 BOOLEAN CreateSuspended = FALSE;
93 ULONG OldPageProtection;
96 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
97 ObjectAttributes.RootDirectory = NULL;
98 ObjectAttributes.ObjectName = NULL;
99 ObjectAttributes.Attributes = 0;
100 if (lpThreadAttributes != NULL)
102 if (lpThreadAttributes->bInheritHandle)
103 ObjectAttributes.Attributes = OBJ_INHERIT;
104 ObjectAttributes.SecurityDescriptor =
105 lpThreadAttributes->lpSecurityDescriptor;
107 ObjectAttributes.SecurityQualityOfService = NULL;
109 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
110 CreateSuspended = TRUE;
112 CreateSuspended = FALSE;
114 InitialTeb.StackReserve = 0x100000; /* 1MByte */
115 /* FIXME: use correct commit size */
117 InitialTeb.StackCommit = (dwStackSize == 0) ? PAGE_SIZE : dwStackSize;
119 InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
121 /* size of guard page */
122 InitialTeb.StackCommit += PAGE_SIZE;
125 InitialTeb.StackAllocate = NULL;
126 Status = NtAllocateVirtualMemory(hProcess,
127 &InitialTeb.StackAllocate,
129 &InitialTeb.StackReserve,
132 if (!NT_SUCCESS(Status))
134 DPRINT("Error reserving stack space!\n");
135 SetLastErrorByStatus(Status);
139 DPRINT("StackDeallocation: %p ReserveSize: 0x%lX\n",
140 InitialTeb.StackDeallocation, InitialTeb.StackReserve);
142 InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
143 InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
145 DPRINT("StackBase: %p\nStackCommit: 0x%lX\n",
146 InitialTeb.StackBase,
147 InitialTeb.StackCommit);
149 /* Commit stack pages */
150 Status = NtAllocateVirtualMemory(hProcess,
151 &InitialTeb.StackLimit,
153 &InitialTeb.StackCommit,
156 if (!NT_SUCCESS(Status))
158 /* release the stack space */
159 NtFreeVirtualMemory(hProcess,
160 InitialTeb.StackAllocate,
161 &InitialTeb.StackReserve,
164 DPRINT("Error comitting stack page(s)!\n");
165 SetLastErrorByStatus(Status);
169 DPRINT("StackLimit: %p\n",
170 InitialTeb.StackLimit);
172 /* Protect guard page */
173 Status = NtProtectVirtualMemory(hProcess,
174 InitialTeb.StackLimit,
176 PAGE_GUARD | PAGE_READWRITE,
178 if (!NT_SUCCESS(Status))
180 /* release the stack space */
181 NtFreeVirtualMemory(hProcess,
182 InitialTeb.StackAllocate,
183 &InitialTeb.StackReserve,
186 DPRINT("Error comitting guard page!\n");
187 SetLastErrorByStatus(Status);
191 memset(&ThreadContext,0,sizeof(CONTEXT));
192 ThreadContext.Eip = (LONG)ThreadStartup;
193 ThreadContext.SegGs = USER_DS;
194 ThreadContext.SegFs = TEB_SELECTOR;
195 ThreadContext.SegEs = USER_DS;
196 ThreadContext.SegDs = USER_DS;
197 ThreadContext.SegCs = USER_CS;
198 ThreadContext.SegSs = USER_DS;
199 ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 12;
200 ThreadContext.EFlags = (1<<1) + (1<<9);
202 /* initialize call stack */
203 *((PULONG)((ULONG)InitialTeb.StackBase - 4)) = (ULONG)lpParameter;
204 *((PULONG)((ULONG)InitialTeb.StackBase - 8)) = (ULONG)lpStartAddress;
205 *((PULONG)((ULONG)InitialTeb.StackBase - 12)) = 0xdeadbeef;
207 DPRINT("Esp: %p\n", ThreadContext.Esp);
208 DPRINT("Eip: %p\n", ThreadContext.Eip);
210 Status = NtCreateThread(&ThreadHandle,
218 if (!NT_SUCCESS(Status))
220 NtFreeVirtualMemory(hProcess,
221 InitialTeb.StackAllocate,
222 &InitialTeb.StackReserve,
225 DPRINT("NtCreateThread() failed!\n");
226 SetLastErrorByStatus(Status);
230 if (lpThreadId != NULL)
231 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
233 return(ThreadHandle);
239 return(NtCurrentTeb());
246 errCode = NtYieldExecution();
253 return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
257 ExitThread(DWORD uExitCode)
264 * Terminate process if this is the last thread
265 * of the current process
267 Status = NtQueryInformationThread(NtCurrentThread(),
272 if (NT_SUCCESS(Status) && LastThread == TRUE)
274 ExitProcess (uExitCode);
277 /* FIXME: notify csrss of thread termination */
281 errCode = NtTerminateThread(NtCurrentThread(),
283 if (!NT_SUCCESS(errCode))
285 SetLastErrorByStatus(errCode);
289 WINBOOL STDCALL GetThreadTimes(HANDLE hThread,
290 LPFILETIME lpCreationTime,
291 LPFILETIME lpExitTime,
292 LPFILETIME lpKernelTime,
293 LPFILETIME lpUserTime)
296 KERNEL_USER_TIMES KernelUserTimes;
299 errCode = NtQueryInformationThread(hThread,
302 sizeof(KERNEL_USER_TIMES),
304 if (!NT_SUCCESS(errCode))
306 SetLastErrorByStatus(errCode);
309 memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
310 memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
311 memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
312 memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
317 WINBOOL STDCALL GetThreadContext(HANDLE hThread,
322 errCode = NtGetContextThread(hThread,
324 if (!NT_SUCCESS(errCode))
326 SetLastErrorByStatus(errCode);
332 WINBOOL STDCALL SetThreadContext(HANDLE hThread,
333 CONST CONTEXT *lpContext)
337 errCode = NtSetContextThread(hThread,
339 if (!NT_SUCCESS(errCode))
341 SetLastErrorByStatus(errCode);
347 WINBOOL STDCALL GetExitCodeThread(HANDLE hThread,
351 THREAD_BASIC_INFORMATION ThreadBasic;
354 errCode = NtQueryInformationThread(hThread,
355 ThreadBasicInformation,
357 sizeof(THREAD_BASIC_INFORMATION),
359 if (!NT_SUCCESS(errCode))
361 SetLastErrorByStatus(errCode);
364 memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
368 DWORD STDCALL ResumeThread(HANDLE hThread)
371 ULONG PreviousResumeCount;
373 errCode = NtResumeThread(hThread,
374 &PreviousResumeCount);
375 if (!NT_SUCCESS(errCode))
377 SetLastErrorByStatus(errCode);
380 return PreviousResumeCount;
385 TerminateThread (HANDLE hThread,
390 SetLastError (ERROR_INVALID_HANDLE);
394 NTSTATUS Status = NtTerminateThread (hThread, dwExitCode);
396 if (NT_SUCCESS(Status))
400 SetLastErrorByStatus (Status);
406 DWORD STDCALL SuspendThread(HANDLE hThread)
409 ULONG PreviousSuspendCount;
411 errCode = NtSuspendThread(hThread,
412 &PreviousSuspendCount);
413 if (!NT_SUCCESS(errCode))
415 SetLastErrorByStatus(errCode);
418 return PreviousSuspendCount;
421 DWORD STDCALL SetThreadAffinityMask(HANDLE hThread,
422 DWORD dwThreadAffinityMask)
427 WINBOOL STDCALL SetThreadPriority(HANDLE hThread,
431 THREAD_BASIC_INFORMATION ThreadBasic;
434 errCode = NtQueryInformationThread(hThread,
435 ThreadBasicInformation,
437 sizeof(THREAD_BASIC_INFORMATION),
439 if (!NT_SUCCESS(errCode))
441 SetLastErrorByStatus(errCode);
444 ThreadBasic.BasePriority = nPriority;
445 errCode = NtSetInformationThread(hThread,
446 ThreadBasicInformation,
448 sizeof(THREAD_BASIC_INFORMATION));
449 if (!NT_SUCCESS(errCode))
451 SetLastErrorByStatus(errCode);
457 int STDCALL GetThreadPriority(HANDLE hThread)
460 THREAD_BASIC_INFORMATION ThreadBasic;
463 errCode = NtQueryInformationThread(hThread,
464 ThreadBasicInformation,
466 sizeof(THREAD_BASIC_INFORMATION),
468 if (!NT_SUCCESS(errCode))
470 SetLastErrorByStatus(errCode);
471 return THREAD_PRIORITY_ERROR_RETURN;
473 return ThreadBasic.BasePriority;