-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/thread/thread.c
* PURPOSE: Thread functions
- * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
- * Tls functions are modified from WINE
- * UPDATE HISTORY:
- * Created 01/11/98
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * Ariadne ( ariadne@xs4all.nl)
*
*/
#define NDEBUG
#include "../include/debug.h"
-
/* FUNCTIONS *****************************************************************/
-
-/* FIXME: please put this in some header */
-static EXCEPTION_DISPOSITION __cdecl
-_except_handler(EXCEPTION_RECORD *ExceptionRecord,
- void * EstablisherFrame,
- CONTEXT *ContextRecord,
- void * DispatcherContext)
+_SEH_FILTER(BaseThreadExceptionFilter)
{
- EXCEPTION_POINTERS ExceptionInfo;
- EXCEPTION_DISPOSITION ExceptionDisposition;
-
- ExceptionInfo.ExceptionRecord = ExceptionRecord;
- ExceptionInfo.ContextRecord = ContextRecord;
+ EXCEPTION_POINTERS * ExceptionInfo = _SEH_GetExceptionPointers();
+ LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
if (GlobalTopLevelExceptionFilter != NULL)
{
_SEH_TRY
{
- ExceptionDisposition = GlobalTopLevelExceptionFilter(&ExceptionInfo);
+ ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
}
_SEH_HANDLE
{
- ExceptionDisposition = UnhandledExceptionFilter(&ExceptionInfo);
+ ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
}
_SEH_END;
}
- else
- {
- ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
- }
-
- if (ExceptionDisposition == EXCEPTION_EXECUTE_HANDLER)
- ExitThread(ExceptionRecord->ExceptionCode);
- /* translate EXCEPTION_XXX defines into EXCEPTION_DISPOSITION enum values */
- if (ExceptionDisposition == EXCEPTION_CONTINUE_EXECUTION)
- return ExceptionContinueExecution;
- else if (ExceptionDisposition == EXCEPTION_CONTINUE_SEARCH)
- return ExceptionContinueSearch;
-
- return -1; /* unknown return from UnhandledExceptionFilter */
+ return ExceptionDisposition;
}
-
-__declspec(noreturn) void STDCALL
-ThreadStartup
-(
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter
-)
+__declspec(noreturn)
+VOID
+STDCALL
+BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter)
{
- volatile UINT uExitCode = 0;
+ volatile UINT uExitCode = 0;
- __try1(_except_handler)
- {
- /* FIXME: notify csrss of thread creation ?? */
- uExitCode = (lpStartAddress)(lpParameter);
- }
- __except1
-
- ExitThread(uExitCode);
+ /* Attempt to call the Thread Start Address */
+ _SEH_TRY
+ {
+ /* Get the exit code from the Thread Start */
+ uExitCode = (lpStartAddress)((PVOID)lpParameter);
+ }
+ _SEH_EXCEPT(BaseThreadExceptionFilter)
+ {
+ /* Get the Exit code from the SEH Handler */
+ uExitCode = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ /* Exit the Thread */
+ ExitThread(uExitCode);
}
-
/*
* @implemented
*/
-HANDLE STDCALL
-CreateThread
-(
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- DWORD dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter,
- DWORD dwCreationFlags,
- LPDWORD lpThreadId
-)
+HANDLE
+STDCALL
+CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId)
{
- return CreateRemoteThread
- (
- NtCurrentProcess(),
- lpThreadAttributes,
- dwStackSize,
- lpStartAddress,
- lpParameter,
- dwCreationFlags,
- lpThreadId
- );
+ /* Act as if we're going to create a remote thread in ourselves */
+ return CreateRemoteThread(NtCurrentProcess(),
+ lpThreadAttributes,
+ dwStackSize,
+ lpStartAddress,
+ lpParameter,
+ dwCreationFlags,
+ lpThreadId);
}
-
/*
* @implemented
*/
-HANDLE STDCALL
-CreateRemoteThread
-(
- HANDLE hProcess,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- DWORD dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter,
- DWORD dwCreationFlags,
- LPDWORD lpThreadId
-)
+HANDLE
+STDCALL
+CreateRemoteThread(HANDLE hProcess,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId)
{
- HANDLE hThread;
- CLIENT_ID cidClientId;
- NTSTATUS nErrCode;
- ULONG_PTR nStackReserve;
- ULONG_PTR nStackCommit;
- OBJECT_ATTRIBUTES oaThreadAttribs;
- PIMAGE_NT_HEADERS pinhHeader =
- RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
-
- DPRINT
- (
- "hProcess %08X\n"
- "lpThreadAttributes %08X\n"
- "dwStackSize %08X\n"
- "lpStartAddress %08X\n"
- "lpParameter %08X\n"
- "dwCreationFlags %08X\n"
- "lpThreadId %08X\n",
- hProcess,
- lpThreadAttributes,
- dwStackSize,
- lpStartAddress,
- lpParameter,
- dwCreationFlags,
- lpThreadId
- );
-
- /* FIXME: do more checks - e.g. the image may not have an optional header */
- if(pinhHeader == NULL)
- {
- nStackReserve = 0x100000;
- nStackCommit = PAGE_SIZE;
- }
- else
- {
- nStackReserve = pinhHeader->OptionalHeader.SizeOfStackReserve;
- nStackCommit = pinhHeader->OptionalHeader.SizeOfStackCommit;
- }
-
- /* FIXME: this should be defined in winbase.h */
-#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
-#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
-#endif
-
- /* use defaults */
- if(dwStackSize == 0);
- /* dwStackSize specifies the size to reserve */
- else if(dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION)
- nStackReserve = dwStackSize;
- /* dwStackSize specifies the size to commit */
- else
- nStackCommit = dwStackSize;
-
- /* fix the stack reserve size */
- if(nStackCommit > nStackReserve)
- nStackReserve = ROUNDUP(nStackCommit, 0x100000);
-
- /* initialize the attributes for the thread object */
- InitializeObjectAttributes
- (
- &oaThreadAttribs,
- NULL,
- 0,
- NULL,
- NULL
- );
-
- if(lpThreadAttributes)
- {
- /* make the handle inheritable */
- if(lpThreadAttributes->bInheritHandle)
- oaThreadAttribs.Attributes |= OBJ_INHERIT;
-
- /* user-defined security descriptor */
- oaThreadAttribs.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
- }
-
- DPRINT
- (
- "RtlRosCreateUserThreadVa\n"
- "(\n"
- " ProcessHandle %p,\n"
- " ObjectAttributes %p,\n"
- " CreateSuspended %d,\n"
- " StackZeroBits %d,\n"
- " StackReserve %lu,\n"
- " StackCommit %lu,\n"
- " StartAddress %p,\n"
- " ThreadHandle %p,\n"
- " ClientId %p,\n"
- " ParameterCount %u,\n"
- " Parameters[0] %p,\n"
- " Parameters[1] %p\n"
- ")\n",
- hProcess,
- &oaThreadAttribs,
- dwCreationFlags & CREATE_SUSPENDED,
- 0,
- nStackReserve,
- nStackCommit,
- ThreadStartup,
- &hThread,
- &cidClientId,
- 2,
- lpStartAddress,
- lpParameter
- );
-
- /* create the thread */
- nErrCode = RtlRosCreateUserThreadVa
- (
- hProcess,
- &oaThreadAttribs,
- dwCreationFlags & CREATE_SUSPENDED,
- 0,
- &nStackReserve,
- &nStackCommit,
- (PTHREAD_START_ROUTINE)ThreadStartup,
- &hThread,
- &cidClientId,
- 2,
- lpStartAddress,
- lpParameter
- );
-
- /* failure */
- if(!NT_SUCCESS(nErrCode))
- {
- SetLastErrorByStatus(nErrCode);
- return NULL;
- }
-
- DPRINT
- (
- "StackReserve %p\n"
- "StackCommit %p\n"
- "ThreadHandle %p\n"
- "ClientId.UniqueThread %p\n",
- nStackReserve,
- nStackCommit,
- hThread,
- cidClientId.UniqueThread
- );
-
- /* success */
- if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
- return hThread;
+ NTSTATUS Status;
+ INITIAL_TEB InitialTeb;
+ CONTEXT Context;
+ CLIENT_ID ClientId;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ POBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hThread;
+ ULONG Dummy;
+
+ DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
+ ": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess,
+ dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
+
+ /* Clear the Context */
+ RtlZeroMemory(&Context, sizeof(CONTEXT));
+
+ /* Write PID */
+ ClientId.UniqueProcess = hProcess;
+
+ /* Create the Stack */
+ Status = BasepCreateStack(hProcess,
+ dwStackSize,
+ dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
+ dwStackSize : 0,
+ &InitialTeb);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return NULL;
+ }
+
+ /* Create Initial Context */
+ BasepInitializeContext(&Context,
+ lpParameter,
+ lpStartAddress,
+ InitialTeb.StackBase,
+ 1);
+
+ /* initialize the attributes for the thread object */
+ ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
+ lpThreadAttributes,
+ NULL);
+
+ /* Create the Kernel Thread Object */
+ Status = NtCreateThread(&hThread,
+ THREAD_ALL_ACCESS,
+ ObjectAttributes,
+ hProcess,
+ &ClientId,
+ &Context,
+ &InitialTeb,
+ TRUE);
+ if(!NT_SUCCESS(Status))
+ {
+ BasepFreeStack(hProcess, &InitialTeb);
+ SetLastErrorByStatus(Status);
+ return NULL;
+ }
+
+ #ifdef SXS_SUPPORT_ENABLED
+ /* Are we in the same process? */
+ if (Process = NtCurrentProcess())
+ {
+ PTEB Teb;
+ PVOID ActivationContextStack;
+ PTHREAD_BASIC_INFORMATION ThreadBasicInfo;
+ PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
+ ULONG_PTR Cookie;
+
+ /* Get the TEB */
+ Status = NtQueryInformationThread(hThread,
+ ThreadBasicIformation,
+ &ThreadBasicInfo,
+ sizeof(ThreadBasicInfo),
+ NULL);
+
+ /* Allocate the Activation Context Stack */
+ Status = RtlAllocateActivationContextStack(&ActivationContextStack);
+ Teb = ThreadBasicInfo.TebBaseAddress;
+
+ /* Save it */
+ Teb->ActivationContextStackPointer = ActivationContextStack;
+
+ /* Query the Context */
+ Status = RtlQueryInformationActivationContext(1,
+ 0,
+ NULL,
+ ActivationContextBasicInformation,
+ &ActivationCtxInfo,
+ sizeof(ActivationCtxInfo),
+ NULL);
+
+ /* Does it need to be activated? */
+ if (!ActivationCtxInfo.hActCtx)
+ {
+ /* Activate it */
+ Status = RtlActivateActivationContextEx(1,
+ Teb,
+ ActivationCtxInfo.hActCtx,
+ &Cookie);
+ }
+ }
+ #endif
+
+ /* FIXME: Notify CSR */
+
+ /* Success */
+ if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;
+
+ /* Resume it if asked */
+ if (!(dwCreationFlags & CREATE_SUSPENDED))
+ {
+ NtResumeThread(hThread, &Dummy);
+ }
+
+ /* Return handle to thread */
+ return hThread;
}
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+ExitThread(DWORD uExitCode)
+{
+ NTSTATUS Status;
+ BOOLEAN LastThread;
+
+ /*
+ * Terminate process if this is the last thread
+ * of the current process
+ */
+ Status = NtQueryInformationThread(NtCurrentThread(),
+ ThreadAmILastThread,
+ &LastThread,
+ sizeof(BOOLEAN),
+ NULL);
+ if (NT_SUCCESS(Status) && LastThread)
+ {
+ /* Exit the Process */
+ ExitProcess(uExitCode);
+ }
+
+ /* Notify DLLs and TLS Callbacks of termination */
+ LdrShutdownThread();
+
+ /* Tell the Kernel to free the Stack */
+ NtCurrentTeb()->FreeStackOnTermination = TRUE;
+ NtTerminateThread(NULL, uExitCode);
+
+ /* We will never reach this place. This silences the compiler */
+ ExitThread(uExitCode);
+}
/*
* @implemented
HANDLE ThreadHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId ;
-
- ClientId.UniqueProcess = INVALID_HANDLE_VALUE;
+
+ ClientId.UniqueProcess = 0;
ClientId.UniqueThread = (HANDLE)dwThreadId;
-
+
InitializeObjectAttributes (&ObjectAttributes,
NULL,
(bInheritHandle ? OBJ_INHERIT : 0),
NULL,
NULL);
-
+
errCode = NtOpenThread(&ThreadHandle,
dwDesiredAccess,
&ObjectAttributes,
return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
}
-/*
- * @implemented
- */
-VOID STDCALL
-ExitThread(DWORD uExitCode)
-{
- NTSTATUS Status;
- BOOLEAN LastThread;
-
- /*
- * Terminate process if this is the last thread
- * of the current process
- */
- Status = NtQueryInformationThread(NtCurrentThread(),
- ThreadAmILastThread,
- &LastThread,
- sizeof(BOOLEAN),
- NULL);
- if (NT_SUCCESS(Status) && LastThread == TRUE)
- {
- ExitProcess(uExitCode);
- }
-
- /* FIXME: notify csrss of thread termination */
-
- LdrShutdownThread();
-
- RtlRosExitUserThread(uExitCode);
-}
-
-
/*
* @implemented
*/
lpCreationTime->dwLowDateTime = KernelUserTimes.CreateTime.u.LowPart;
lpCreationTime->dwHighDateTime = KernelUserTimes.CreateTime.u.HighPart;
-
+
lpExitTime->dwLowDateTime = KernelUserTimes.ExitTime.u.LowPart;
lpExitTime->dwHighDateTime = KernelUserTimes.ExitTime.u.HighPart;
-
+
lpKernelTime->dwLowDateTime = KernelUserTimes.KernelTime.u.LowPart;
lpKernelTime->dwHighDateTime = KernelUserTimes.KernelTime.u.HighPart;
-
+
lpUserTime->dwLowDateTime = KernelUserTimes.UserTime.u.LowPart;
lpUserTime->dwHighDateTime = KernelUserTimes.UserTime.u.HighPart;
{
DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
NTSTATUS Status;
-
+
DescriptionTableEntry.Selector = dwSelector;
Status = NtQueryInformationThread(hThread,
ThreadDescriptorTableEntry,
/*
* @unimplemented
*/
-VOID STDCALL
-SetThreadUILanguage(DWORD Unknown1)
+LANGID STDCALL
+SetThreadUILanguage(WORD wReserved)
{
- DPRINT1("SetThreadUILanguage(0x%x) unimplemented!\n", Unknown1);
+ DPRINT1("SetThreadUILanguage(0x%4x) unimplemented!\n", wReserved);
+ return 0;
}
static void CALLBACK
{
ULONG IoPending;
NTSTATUS Status;
-
+
if(lpIOIsPending == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
-
+
Status = NtQueryInformationThread(hThread,
ThreadIsIoPending,
(PVOID)&IoPending,
*lpIOIsPending = ((IoPending != 0) ? TRUE : FALSE);
return TRUE;
}
-
+
SetLastErrorByStatus(Status);
return FALSE;
}