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 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Ariadne ( ariadne@xs4all.nl)
11 /* INCLUDES ******************************************************************/
16 #include "../include/debug.h"
18 /* FUNCTIONS *****************************************************************/
19 _SEH_FILTER(BaseThreadExceptionFilter
)
21 EXCEPTION_POINTERS
* ExceptionInfo
= _SEH_GetExceptionPointers();
22 LONG ExceptionDisposition
= EXCEPTION_EXECUTE_HANDLER
;
24 if (GlobalTopLevelExceptionFilter
!= NULL
)
28 ExceptionDisposition
= GlobalTopLevelExceptionFilter(ExceptionInfo
);
32 ExceptionDisposition
= UnhandledExceptionFilter(ExceptionInfo
);
37 return ExceptionDisposition
;
43 BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress
,
46 volatile UINT uExitCode
= 0;
48 /* Attempt to call the Thread Start Address */
51 /* Get the exit code from the Thread Start */
52 uExitCode
= (lpStartAddress
)((PVOID
)lpParameter
);
54 _SEH_EXCEPT(BaseThreadExceptionFilter
)
56 /* Get the Exit code from the SEH Handler */
57 uExitCode
= _SEH_GetExceptionCode();
61 ExitThread(uExitCode
);
69 CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes
,
71 LPTHREAD_START_ROUTINE lpStartAddress
,
73 DWORD dwCreationFlags
,
76 /* Act as if we're going to create a remote thread in ourselves */
77 return CreateRemoteThread(NtCurrentProcess(),
91 CreateRemoteThread(HANDLE hProcess
,
92 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
94 LPTHREAD_START_ROUTINE lpStartAddress
,
96 DWORD dwCreationFlags
,
100 INITIAL_TEB InitialTeb
;
103 OBJECT_ATTRIBUTES LocalObjectAttributes
;
104 POBJECT_ATTRIBUTES ObjectAttributes
;
108 DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
109 ": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess
,
110 dwStackSize
, lpStartAddress
, lpParameter
, dwCreationFlags
);
112 /* Clear the Context */
113 RtlZeroMemory(&Context
, sizeof(CONTEXT
));
116 ClientId
.UniqueProcess
= hProcess
;
118 /* Create the Stack */
119 Status
= BasepCreateStack(hProcess
,
121 dwCreationFlags
& STACK_SIZE_PARAM_IS_A_RESERVATION
?
124 if(!NT_SUCCESS(Status
))
126 SetLastErrorByStatus(Status
);
130 /* Create Initial Context */
131 BasepInitializeContext(&Context
,
134 InitialTeb
.StackBase
,
137 /* initialize the attributes for the thread object */
138 ObjectAttributes
= BasepConvertObjectAttributes(&LocalObjectAttributes
,
142 /* Create the Kernel Thread Object */
143 Status
= NtCreateThread(&hThread
,
151 if(!NT_SUCCESS(Status
))
153 BasepFreeStack(hProcess
, &InitialTeb
);
154 SetLastErrorByStatus(Status
);
158 #ifdef SXS_SUPPORT_ENABLED
159 /* Are we in the same process? */
160 if (Process
= NtCurrentProcess())
163 PVOID ActivationContextStack
;
164 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
;
165 PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo
;
169 Status
= NtQueryInformationThread(hThread
,
170 ThreadBasicIformation
,
172 sizeof(ThreadBasicInfo
),
175 /* Allocate the Activation Context Stack */
176 Status
= RtlAllocateActivationContextStack(&ActivationContextStack
);
177 Teb
= ThreadBasicInfo
.TebBaseAddress
;
180 Teb
->ActivationContextStackPointer
= ActivationContextStack
;
182 /* Query the Context */
183 Status
= RtlQueryInformationActivationContext(1,
186 ActivationContextBasicInformation
,
188 sizeof(ActivationCtxInfo
),
191 /* Does it need to be activated? */
192 if (!ActivationCtxInfo
.hActCtx
)
195 Status
= RtlActivateActivationContextEx(1,
197 ActivationCtxInfo
.hActCtx
,
203 /* FIXME: Notify CSR */
206 if(lpThreadId
) *lpThreadId
= (DWORD
)ClientId
.UniqueThread
;
208 /* Resume it if asked */
209 if (!(dwCreationFlags
& CREATE_SUSPENDED
))
211 NtResumeThread(hThread
, &Dummy
);
214 /* Return handle to thread */
223 ExitThread(DWORD uExitCode
)
229 * Terminate process if this is the last thread
230 * of the current process
232 Status
= NtQueryInformationThread(NtCurrentThread(),
237 if (NT_SUCCESS(Status
) && LastThread
)
239 /* Exit the Process */
240 ExitProcess(uExitCode
);
243 /* Notify DLLs and TLS Callbacks of termination */
246 /* Tell the Kernel to free the Stack */
247 NtCurrentTeb()->FreeStackOnTermination
= TRUE
;
248 NtTerminateThread(NULL
, uExitCode
);
250 /* We will never reach this place. This silences the compiler */
251 ExitThread(uExitCode
);
260 DWORD dwDesiredAccess
,
267 OBJECT_ATTRIBUTES ObjectAttributes
;
270 ClientId
.UniqueProcess
= INVALID_HANDLE_VALUE
;
271 ClientId
.UniqueThread
= (HANDLE
)dwThreadId
;
273 InitializeObjectAttributes (&ObjectAttributes
,
275 (bInheritHandle
? OBJ_INHERIT
: 0),
279 errCode
= NtOpenThread(&ThreadHandle
,
283 if (!NT_SUCCESS(errCode
))
285 SetLastErrorByStatus (errCode
);
298 return(NtCurrentTeb());
309 Status
= NtYieldExecution();
310 return Status
!= STATUS_NO_YIELD_PERFORMED
;
318 GetCurrentThreadId(VOID
)
320 return((DWORD
)(NtCurrentTeb()->Cid
).UniqueThread
);
327 GetThreadTimes(HANDLE hThread
,
328 LPFILETIME lpCreationTime
,
329 LPFILETIME lpExitTime
,
330 LPFILETIME lpKernelTime
,
331 LPFILETIME lpUserTime
)
333 KERNEL_USER_TIMES KernelUserTimes
;
336 Status
= NtQueryInformationThread(hThread
,
339 sizeof(KERNEL_USER_TIMES
),
341 if (!NT_SUCCESS(Status
))
343 SetLastErrorByStatus(Status
);
347 lpCreationTime
->dwLowDateTime
= KernelUserTimes
.CreateTime
.u
.LowPart
;
348 lpCreationTime
->dwHighDateTime
= KernelUserTimes
.CreateTime
.u
.HighPart
;
350 lpExitTime
->dwLowDateTime
= KernelUserTimes
.ExitTime
.u
.LowPart
;
351 lpExitTime
->dwHighDateTime
= KernelUserTimes
.ExitTime
.u
.HighPart
;
353 lpKernelTime
->dwLowDateTime
= KernelUserTimes
.KernelTime
.u
.LowPart
;
354 lpKernelTime
->dwHighDateTime
= KernelUserTimes
.KernelTime
.u
.HighPart
;
356 lpUserTime
->dwLowDateTime
= KernelUserTimes
.UserTime
.u
.LowPart
;
357 lpUserTime
->dwHighDateTime
= KernelUserTimes
.UserTime
.u
.HighPart
;
367 GetThreadContext(HANDLE hThread
,
372 Status
= NtGetContextThread(hThread
,
374 if (!NT_SUCCESS(Status
))
376 SetLastErrorByStatus(Status
);
388 SetThreadContext(HANDLE hThread
,
389 CONST CONTEXT
*lpContext
)
393 Status
= NtSetContextThread(hThread
,
395 if (!NT_SUCCESS(Status
))
397 SetLastErrorByStatus(Status
);
409 GetExitCodeThread(HANDLE hThread
,
412 THREAD_BASIC_INFORMATION ThreadBasic
;
415 Status
= NtQueryInformationThread(hThread
,
416 ThreadBasicInformation
,
418 sizeof(THREAD_BASIC_INFORMATION
),
420 if (!NT_SUCCESS(Status
))
422 SetLastErrorByStatus(Status
);
426 memcpy(lpExitCode
, &ThreadBasic
.ExitStatus
, sizeof(DWORD
));
436 ResumeThread(HANDLE hThread
)
438 ULONG PreviousResumeCount
;
441 Status
= NtResumeThread(hThread
,
442 &PreviousResumeCount
);
443 if (!NT_SUCCESS(Status
))
445 SetLastErrorByStatus(Status
);
449 return(PreviousResumeCount
);
457 TerminateThread(HANDLE hThread
,
464 SetLastError(ERROR_INVALID_HANDLE
);
468 Status
= NtTerminateThread(hThread
,
470 if (!NT_SUCCESS(Status
))
472 SetLastErrorByStatus(Status
);
484 SuspendThread(HANDLE hThread
)
486 ULONG PreviousSuspendCount
;
489 Status
= NtSuspendThread(hThread
,
490 &PreviousSuspendCount
);
491 if (!NT_SUCCESS(Status
))
493 SetLastErrorByStatus(Status
);
497 return(PreviousSuspendCount
);
505 SetThreadAffinityMask(HANDLE hThread
,
506 DWORD dwThreadAffinityMask
)
508 THREAD_BASIC_INFORMATION ThreadBasic
;
509 KAFFINITY AffinityMask
;
512 AffinityMask
= (KAFFINITY
)dwThreadAffinityMask
;
514 Status
= NtQueryInformationThread(hThread
,
515 ThreadBasicInformation
,
517 sizeof(THREAD_BASIC_INFORMATION
),
519 if (!NT_SUCCESS(Status
))
521 SetLastErrorByStatus(Status
);
525 Status
= NtSetInformationThread(hThread
,
529 if (!NT_SUCCESS(Status
))
530 SetLastErrorByStatus(Status
);
532 return(ThreadBasic
.AffinityMask
);
540 SetThreadPriority(HANDLE hThread
,
543 ULONG Prio
= nPriority
;
546 Status
= NtSetInformationThread(hThread
,
551 if (!NT_SUCCESS(Status
))
553 SetLastErrorByStatus(Status
);
565 GetThreadPriority(HANDLE hThread
)
567 THREAD_BASIC_INFORMATION ThreadBasic
;
570 Status
= NtQueryInformationThread(hThread
,
571 ThreadBasicInformation
,
573 sizeof(THREAD_BASIC_INFORMATION
),
575 if (!NT_SUCCESS(Status
))
577 SetLastErrorByStatus(Status
);
578 return(THREAD_PRIORITY_ERROR_RETURN
);
581 return(ThreadBasic
.BasePriority
);
589 GetThreadPriorityBoost(IN HANDLE hThread
,
590 OUT PBOOL pDisablePriorityBoost
)
595 Status
= NtQueryInformationThread(hThread
,
600 if (!NT_SUCCESS(Status
))
602 SetLastErrorByStatus(Status
);
606 *pDisablePriorityBoost
= !((BOOL
)PriorityBoost
);
616 SetThreadPriorityBoost(IN HANDLE hThread
,
617 IN BOOL bDisablePriorityBoost
)
622 PriorityBoost
= (ULONG
)!bDisablePriorityBoost
;
624 Status
= NtSetInformationThread(hThread
,
628 if (!NT_SUCCESS(Status
))
630 SetLastErrorByStatus(Status
);
642 GetThreadSelectorEntry(IN HANDLE hThread
,
644 OUT LPLDT_ENTRY lpSelectorEntry
)
646 DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry
;
649 DescriptionTableEntry
.Selector
= dwSelector
;
650 Status
= NtQueryInformationThread(hThread
,
651 ThreadDescriptorTableEntry
,
652 &DescriptionTableEntry
,
653 sizeof(DESCRIPTOR_TABLE_ENTRY
),
655 if(!NT_SUCCESS(Status
))
657 SetLastErrorByStatus(Status
);
661 *lpSelectorEntry
= DescriptionTableEntry
.Descriptor
;
670 SetThreadIdealProcessor(HANDLE hThread
,
671 DWORD dwIdealProcessor
)
675 Status
= NtSetInformationThread(hThread
,
676 ThreadIdealProcessor
,
679 if (!NT_SUCCESS(Status
))
681 SetLastErrorByStatus(Status
);
685 return dwIdealProcessor
;
693 GetProcessIdOfThread(HANDLE Thread
)
695 THREAD_BASIC_INFORMATION ThreadBasic
;
698 Status
= NtQueryInformationThread(Thread
,
699 ThreadBasicInformation
,
701 sizeof(THREAD_BASIC_INFORMATION
),
703 if(!NT_SUCCESS(Status
))
705 SetLastErrorByStatus(Status
);
709 return (DWORD
)ThreadBasic
.ClientId
.UniqueProcess
;
717 GetThreadId(HANDLE Thread
)
719 THREAD_BASIC_INFORMATION ThreadBasic
;
722 Status
= NtQueryInformationThread(Thread
,
723 ThreadBasicInformation
,
725 sizeof(THREAD_BASIC_INFORMATION
),
727 if(!NT_SUCCESS(Status
))
729 SetLastErrorByStatus(Status
);
733 return (DWORD
)ThreadBasic
.ClientId
.UniqueThread
;
740 SetThreadUILanguage(DWORD Unknown1
)
742 DPRINT1("SetThreadUILanguage(0x%x) unimplemented!\n", Unknown1
);
746 IntCallUserApc(PVOID Function
, PVOID dwData
, PVOID Argument3
)
748 PAPCFUNC pfnAPC
= (PAPCFUNC
)Function
;
749 pfnAPC((ULONG_PTR
)dwData
);
756 QueueUserAPC(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
)
760 Status
= NtQueueApcThread(hThread
, IntCallUserApc
, pfnAPC
,
761 (PVOID
)dwData
, NULL
);
763 SetLastErrorByStatus(Status
);
765 return NT_SUCCESS(Status
);
772 GetThreadIOPendingFlag(HANDLE hThread
,
778 if(lpIOIsPending
== NULL
)
780 SetLastError(ERROR_INVALID_PARAMETER
);
784 Status
= NtQueryInformationThread(hThread
,
789 if(NT_SUCCESS(Status
))
791 *lpIOIsPending
= ((IoPending
!= 0) ? TRUE
: FALSE
);
795 SetLastErrorByStatus(Status
);
804 Sleep(DWORD dwMilliseconds
)
806 SleepEx(dwMilliseconds
, FALSE
);
815 SleepEx(DWORD dwMilliseconds
,
818 LARGE_INTEGER Interval
;
821 if (dwMilliseconds
!= INFINITE
)
824 * System time units are 100 nanoseconds (a nanosecond is a billionth of
827 Interval
.QuadPart
= -((ULONGLONG
)dwMilliseconds
* 10000);
831 /* Approximately 292000 years hence */
832 Interval
.QuadPart
= -0x7FFFFFFFFFFFFFFFLL
;
835 errCode
= NtDelayExecution ((bAlertable
? TRUE
: FALSE
), &Interval
);
836 if (!NT_SUCCESS(errCode
))
838 SetLastErrorByStatus (errCode
);