reactos/reactos/lib/kernel32/thread/thread.c

323 lines
8 KiB
C
Raw Normal View History

/*
* 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
*/
/* INCLUDES ******************************************************************/
#include <windows.h>
#include <kernel32/thread.h>
#include <ddk/ntddk.h>
#include <string.h>
#include <internal/i386/segment.h>
//#define NDEBUG
#include <kernel32/kernel32.h>
/* FUNCTIONS *****************************************************************/
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));
}
HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId)
{
HANDLE ThreadHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
CONTEXT ThreadContext;
INITIAL_TEB InitialTeb;
BOOLEAN CreateSuspended = FALSE;
PVOID BaseAddress;
DWORD StackSize;
ULONG BytesWritten;
NTSTATUS Status;
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = NULL;
ObjectAttributes.Attributes = 0;
if (lpThreadAttributes != NULL)
{
if (lpThreadAttributes->bInheritHandle)
ObjectAttributes.Attributes = OBJ_INHERIT;
ObjectAttributes.SecurityDescriptor =
lpThreadAttributes->lpSecurityDescriptor;
}
ObjectAttributes.SecurityQualityOfService = NULL;
if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
CreateSuspended = TRUE;
else
CreateSuspended = FALSE;
StackSize = (dwStackSize == 0) ? 4096 : dwStackSize;
BaseAddress = 0;
Status = NtAllocateVirtualMemory(hProcess,
&BaseAddress,
0,
(PULONG)&StackSize,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Could not allocate stack space!\n");
return NULL;
}
DPRINT("Stack base address: %p\n", BaseAddress);
memset(&ThreadContext,0,sizeof(CONTEXT));
ThreadContext.Eip = (LONG)lpStartAddress;
ThreadContext.SegGs = USER_DS;
ThreadContext.SegFs = USER_DS;
ThreadContext.SegEs = USER_DS;
ThreadContext.SegDs = USER_DS;
ThreadContext.SegCs = USER_CS;
ThreadContext.SegSs = USER_DS;
ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 8);
ThreadContext.EFlags = (1<<1) + (1<<9);
/* write lpParameter to highest stack address */
*((PBYTE)(BaseAddress + StackSize - 4)) = lpParameter;
Status = NtCreateThread(&ThreadHandle,
THREAD_ALL_ACCESS,
&ObjectAttributes,
hProcess,
&ClientId,
&ThreadContext,
&InitialTeb,
CreateSuspended);
if (!NT_SUCCESS(Status))
{
DPRINT("NtCreateThread() failed!\n");
return NULL;
}
if ( lpThreadId != NULL )
memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
return ThreadHandle;
}
NT_TEB *GetTeb(VOID)
{
return NULL;
}
WINBOOL STDCALL SwitchToThread(VOID)
{
NTSTATUS errCode;
errCode = NtYieldExecution();
return TRUE;
}
DWORD STDCALL GetCurrentThreadId()
{
return((DWORD)(GetTeb()->Cid).UniqueThread);
}
VOID STDCALL ExitThread(UINT uExitCode)
{
NTSTATUS errCode;
errCode = NtTerminateThread(NtCurrentThread(),
uExitCode);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
}
}
WINBOOL STDCALL GetThreadTimes(HANDLE hThread,
LPFILETIME lpCreationTime,
LPFILETIME lpExitTime,
LPFILETIME lpKernelTime,
LPFILETIME lpUserTime)
{
NTSTATUS errCode;
KERNEL_USER_TIMES KernelUserTimes;
ULONG ReturnLength;
errCode = NtQueryInformationThread(hThread,
ThreadTimes,
&KernelUserTimes,
sizeof(KERNEL_USER_TIMES),
&ReturnLength);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME));
memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME));
memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME));
memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME));
return TRUE;
}
WINBOOL STDCALL GetThreadContext(HANDLE hThread,
LPCONTEXT lpContext)
{
NTSTATUS errCode;
errCode = NtGetContextThread(hThread,
lpContext);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
return TRUE;
}
WINBOOL STDCALL SetThreadContext(HANDLE hThread,
CONST CONTEXT *lpContext)
{
NTSTATUS errCode;
errCode = NtSetContextThread(hThread,
(void *)lpContext);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
return TRUE;
}
WINBOOL STDCALL GetExitCodeThread(HANDLE hThread,
LPDWORD lpExitCode)
{
NTSTATUS errCode;
THREAD_BASIC_INFORMATION ThreadBasic;
ULONG DataWritten;
errCode = NtQueryInformationThread(hThread,
ThreadBasicInformation,
&ThreadBasic,
sizeof(THREAD_BASIC_INFORMATION),
&DataWritten);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
return TRUE;
}
DWORD STDCALL ResumeThread(HANDLE hThread)
{
NTSTATUS errCode;
ULONG PreviousResumeCount;
errCode = NtResumeThread(hThread,
&PreviousResumeCount);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return -1;
}
return PreviousResumeCount;
}
DWORD STDCALL SuspendThread(HANDLE hThread)
{
NTSTATUS errCode;
ULONG PreviousSuspendCount;
errCode = NtSuspendThread(hThread,
&PreviousSuspendCount);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return -1;
}
return PreviousSuspendCount;
}
DWORD STDCALL SetThreadAffinityMask(HANDLE hThread,
DWORD dwThreadAffinityMask)
{
return 0;
}
WINBOOL STDCALL SetThreadPriority(HANDLE hThread,
int nPriority)
{
NTSTATUS errCode;
THREAD_BASIC_INFORMATION ThreadBasic;
ULONG DataWritten;
errCode = NtQueryInformationThread(hThread,
ThreadBasicInformation,
&ThreadBasic,
sizeof(THREAD_BASIC_INFORMATION),
&DataWritten);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
ThreadBasic.BasePriority = nPriority;
errCode = NtSetInformationThread(hThread,
ThreadBasicInformation,
&ThreadBasic,
sizeof(THREAD_BASIC_INFORMATION));
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return FALSE;
}
return TRUE;
}
int STDCALL GetThreadPriority(HANDLE hThread)
{
NTSTATUS errCode;
THREAD_BASIC_INFORMATION ThreadBasic;
ULONG DataWritten;
errCode = NtQueryInformationThread(hThread,
ThreadBasicInformation,
&ThreadBasic,
sizeof(THREAD_BASIC_INFORMATION),
&DataWritten);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return THREAD_PRIORITY_ERROR_RETURN;
}
return ThreadBasic.BasePriority;
}