1 /* $Id: thread.c,v 1.20 2000/09/05 23:01:07 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>
18 #include <ntdll/ldr.h>
20 #include <napi/i386/segment.h>
23 #include <kernel32/kernel32.h>
24 #include <kernel32/error.h>
27 static VOID
ThreadAttachDlls (VOID
);
29 /* Type for a DLL's entry point */
35 ULONG ul_reason_for_call
,
39 /* FUNCTIONS *****************************************************************/
42 ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress
,
49 /* FIXME: notify csrss of thread creation ?? */
51 uExitCode
= (lpStartAddress
)(lpParameter
);
53 ExitThread(uExitCode
);
57 ThreadAttachDlls (VOID
)
59 PLIST_ENTRY ModuleListHead
;
63 DPRINT("ThreadAttachDlls() called\n");
65 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
67 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
68 Entry
= ModuleListHead
->Blink
;
70 while (Entry
!= ModuleListHead
)
72 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InInitializationOrderModuleList
);
74 if (Module
->EntryPoint
!= 0)
76 PDLLMAIN_FUNC Entrypoint
= (PDLLMAIN_FUNC
)Module
->EntryPoint
;
78 DPRINT("Calling entry point at 0x%08x\n", Entrypoint
);
79 Entrypoint (Module
->BaseAddress
,
87 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
89 DPRINT("ThreadAttachDlls() done\n");
92 HANDLE STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
94 LPTHREAD_START_ROUTINE lpStartAddress
,
96 DWORD dwCreationFlags
,
99 return(CreateRemoteThread(NtCurrentProcess(),
108 HANDLE STDCALL
CreateRemoteThread(HANDLE hProcess
,
109 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
111 LPTHREAD_START_ROUTINE lpStartAddress
,
113 DWORD dwCreationFlags
,
117 OBJECT_ATTRIBUTES ObjectAttributes
;
119 CONTEXT ThreadContext
;
120 INITIAL_TEB InitialTeb
;
121 BOOLEAN CreateSuspended
= FALSE
;
126 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
127 ObjectAttributes
.RootDirectory
= NULL
;
128 ObjectAttributes
.ObjectName
= NULL
;
129 ObjectAttributes
.Attributes
= 0;
130 if (lpThreadAttributes
!= NULL
)
132 if (lpThreadAttributes
->bInheritHandle
)
133 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
134 ObjectAttributes
.SecurityDescriptor
=
135 lpThreadAttributes
->lpSecurityDescriptor
;
137 ObjectAttributes
.SecurityQualityOfService
= NULL
;
139 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
140 CreateSuspended
= TRUE
;
142 CreateSuspended
= FALSE
;
144 StackSize
= (dwStackSize
== 0) ? 4096 : dwStackSize
;
148 Status
= NtAllocateVirtualMemory(hProcess
,
154 if (!NT_SUCCESS(Status
))
156 DPRINT("Could not allocate stack space!\n");
161 DPRINT("Stack base address: %p\n", BaseAddress
);
163 memset(&ThreadContext
,0,sizeof(CONTEXT
));
164 ThreadContext
.Eip
= (LONG
)ThreadStartup
;
165 ThreadContext
.SegGs
= USER_DS
;
166 ThreadContext
.SegFs
= USER_DS
;
167 ThreadContext
.SegEs
= USER_DS
;
168 ThreadContext
.SegDs
= USER_DS
;
169 ThreadContext
.SegCs
= USER_CS
;
170 ThreadContext
.SegSs
= USER_DS
;
171 ThreadContext
.Esp
= (ULONG
)(BaseAddress
+ StackSize
- 12);
172 ThreadContext
.EFlags
= (1<<1) + (1<<9);
174 /* initialize call stack */
175 *((PULONG
)(BaseAddress
+ StackSize
- 4)) = (ULONG
)lpParameter
;
176 *((PULONG
)(BaseAddress
+ StackSize
- 8)) = (ULONG
)lpStartAddress
;
177 *((PULONG
)(BaseAddress
+ StackSize
- 12)) = 0xdeadbeef;
179 DPRINT("Esp: %p\n", ThreadContext
.Esp
);
180 DPRINT("Eip: %p\n", ThreadContext
.Eip
);
182 Status
= NtCreateThread(&ThreadHandle
,
191 if (!NT_SUCCESS(Status
))
193 DPRINT("NtCreateThread() failed!\n");
197 if ( lpThreadId
!= NULL
)
198 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
205 return NtCurrentTeb();
208 WINBOOL STDCALL
SwitchToThread(VOID
)
211 errCode
= NtYieldExecution();
215 DWORD STDCALL
GetCurrentThreadId()
217 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
220 VOID STDCALL
ExitThread(UINT uExitCode
)
227 * Terminate process if this is the last thread
228 * of the current process
230 Status
= NtQueryInformationThread(NtCurrentThread(),
235 if (NT_SUCCESS(Status
) && LastThread
== TRUE
)
237 ExitProcess (uExitCode
);
240 /* FIXME: notify csrss of thread termination */
244 errCode
= NtTerminateThread(NtCurrentThread(),
246 if (!NT_SUCCESS(errCode
))
248 SetLastErrorByStatus(errCode
);
252 WINBOOL STDCALL
GetThreadTimes(HANDLE hThread
,
253 LPFILETIME lpCreationTime
,
254 LPFILETIME lpExitTime
,
255 LPFILETIME lpKernelTime
,
256 LPFILETIME lpUserTime
)
259 KERNEL_USER_TIMES KernelUserTimes
;
262 errCode
= NtQueryInformationThread(hThread
,
265 sizeof(KERNEL_USER_TIMES
),
267 if (!NT_SUCCESS(errCode
))
269 SetLastErrorByStatus(errCode
);
272 memcpy(lpCreationTime
, &KernelUserTimes
.CreateTime
, sizeof(FILETIME
));
273 memcpy(lpExitTime
, &KernelUserTimes
.ExitTime
, sizeof(FILETIME
));
274 memcpy(lpKernelTime
, &KernelUserTimes
.KernelTime
, sizeof(FILETIME
));
275 memcpy(lpUserTime
, &KernelUserTimes
.UserTime
, sizeof(FILETIME
));
280 WINBOOL STDCALL
GetThreadContext(HANDLE hThread
,
285 errCode
= NtGetContextThread(hThread
,
287 if (!NT_SUCCESS(errCode
))
289 SetLastErrorByStatus(errCode
);
295 WINBOOL STDCALL
SetThreadContext(HANDLE hThread
,
296 CONST CONTEXT
*lpContext
)
300 errCode
= NtSetContextThread(hThread
,
302 if (!NT_SUCCESS(errCode
))
304 SetLastErrorByStatus(errCode
);
310 WINBOOL STDCALL
GetExitCodeThread(HANDLE hThread
,
314 THREAD_BASIC_INFORMATION ThreadBasic
;
317 errCode
= NtQueryInformationThread(hThread
,
318 ThreadBasicInformation
,
320 sizeof(THREAD_BASIC_INFORMATION
),
322 if (!NT_SUCCESS(errCode
))
324 SetLastErrorByStatus(errCode
);
327 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
331 DWORD STDCALL
ResumeThread(HANDLE hThread
)
334 ULONG PreviousResumeCount
;
336 errCode
= NtResumeThread(hThread
,
337 &PreviousResumeCount
);
338 if (!NT_SUCCESS(errCode
))
340 SetLastErrorByStatus(errCode
);
343 return PreviousResumeCount
;
356 errCode
= NtTerminateThread(hThread
,
358 if (!NT_SUCCESS(errCode
))
360 SetLastErrorByStatus(errCode
);
367 DWORD STDCALL
SuspendThread(HANDLE hThread
)
370 ULONG PreviousSuspendCount
;
372 errCode
= NtSuspendThread(hThread
,
373 &PreviousSuspendCount
);
374 if (!NT_SUCCESS(errCode
))
376 SetLastErrorByStatus(errCode
);
379 return PreviousSuspendCount
;
382 DWORD STDCALL
SetThreadAffinityMask(HANDLE hThread
,
383 DWORD dwThreadAffinityMask
)
388 WINBOOL STDCALL
SetThreadPriority(HANDLE hThread
,
392 THREAD_BASIC_INFORMATION ThreadBasic
;
395 errCode
= NtQueryInformationThread(hThread
,
396 ThreadBasicInformation
,
398 sizeof(THREAD_BASIC_INFORMATION
),
400 if (!NT_SUCCESS(errCode
))
402 SetLastErrorByStatus(errCode
);
405 ThreadBasic
.BasePriority
= nPriority
;
406 errCode
= NtSetInformationThread(hThread
,
407 ThreadBasicInformation
,
409 sizeof(THREAD_BASIC_INFORMATION
));
410 if (!NT_SUCCESS(errCode
))
412 SetLastErrorByStatus(errCode
);
418 int STDCALL
GetThreadPriority(HANDLE hThread
)
421 THREAD_BASIC_INFORMATION ThreadBasic
;
424 errCode
= NtQueryInformationThread(hThread
,
425 ThreadBasicInformation
,
427 sizeof(THREAD_BASIC_INFORMATION
),
429 if (!NT_SUCCESS(errCode
))
431 SetLastErrorByStatus(errCode
);
432 return THREAD_PRIORITY_ERROR_RETURN
;
434 return ThreadBasic
.BasePriority
;