* 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)
+ *
*/
-#include <windows.h>
-#include <kernel32/thread.h>
-#include <ddk/ntddk.h>
-#include <string.h>
+/* INCLUDES ******************************************************************/
+#include <k32.h>
-HANDLE
-STDCALL
-CreateThread(
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- DWORD dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter,
- DWORD dwCreationFlags,
- LPDWORD lpThreadId
- )
+#define NDEBUG
+#include "../include/debug.h"
+
+/* FUNCTIONS *****************************************************************/
+_SEH_FILTER(BaseThreadExceptionFilter)
{
- return CreateRemoteThread(NtCurrentProcess(),lpThreadAttributes,dwStackSize,
- lpStartAddress,lpParameter,dwCreationFlags,lpThreadId);
+ EXCEPTION_POINTERS * ExceptionInfo = _SEH_GetExceptionPointers();
+ LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
+
+ if (GlobalTopLevelExceptionFilter != NULL)
+ {
+ _SEH_TRY
+ {
+ ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
+ }
+ _SEH_HANDLE
+ {
+ ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
+ }
+ _SEH_END;
+ }
+
+ return ExceptionDisposition;
}
+__declspec(noreturn)
+VOID
+STDCALL
+BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter)
+{
+ volatile UINT uExitCode = 0;
+
+ /* 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
-CreateRemoteThread(
- HANDLE hProcess,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- DWORD dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter,
- DWORD dwCreationFlags,
- LPDWORD lpThreadId
- )
-{
- NTSTATUS errCode;
- HANDLE ThreadHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- CLIENT_ID ClientId;
- CONTEXT ThreadContext;
- INITIAL_TEB InitialTeb;
- BOOLEAN CreateSuspended = FALSE;
-
- 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;
- // fix context
- GetThreadContext(NtCurrentThread(),&ThreadContext);
- // fix teb [ stack context ] --> check the image file
-
- errCode = NtCreateThread(
- &ThreadHandle,
- THREAD_ALL_ACCESS,
- &ObjectAttributes,
- hProcess,
- &ClientId,
- &ThreadContext,
- &InitialTeb,
- CreateSuspended
- );
- if ( lpThreadId != NULL )
- memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
-
- return ThreadHandle;
+CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId)
+{
+ /* Act as if we're going to create a remote thread in ourselves */
+ return CreateRemoteThread(NtCurrentProcess(),
+ lpThreadAttributes,
+ dwStackSize,
+ lpStartAddress,
+ lpParameter,
+ dwCreationFlags,
+ lpThreadId);
}
-NT_TEB *GetTeb(VOID)
+/*
+ * @implemented
+ */
+HANDLE
+STDCALL
+CreateRemoteThread(HANDLE hProcess,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId)
{
- return NULL;
+ 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;
}
-WINBOOL STDCALL
-SwitchToThread(VOID )
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+ExitThread(DWORD uExitCode)
{
- NTSTATUS errCode;
- errCode = NtYieldExecution();
- return TRUE;
+ 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);
}
-DWORD
+/*
+ * @implemented
+ */
+HANDLE
STDCALL
-GetCurrentThreadId()
+OpenThread(
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ DWORD dwThreadId
+ )
{
+ NTSTATUS errCode;
+ HANDLE ThreadHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ CLIENT_ID ClientId ;
+
+ ClientId.UniqueProcess = 0;
+ ClientId.UniqueThread = (HANDLE)dwThreadId;
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ NULL,
+ (bInheritHandle ? OBJ_INHERIT : 0),
+ NULL,
+ NULL);
+
+ errCode = NtOpenThread(&ThreadHandle,
+ dwDesiredAccess,
+ &ObjectAttributes,
+ &ClientId);
+ if (!NT_SUCCESS(errCode))
+ {
+ SetLastErrorByStatus (errCode);
+ return NULL;
+ }
+ return ThreadHandle;
+}
+
- return (DWORD)(GetTeb()->Cid).UniqueThread;
+/*
+ * @implemented
+ */
+PTEB
+GetTeb(VOID)
+{
+ return(NtCurrentTeb());
}
-VOID
-STDCALL
-ExitThread(
- UINT uExitCode
- )
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SwitchToThread(VOID)
{
- NTSTATUS errCode;
-
- errCode = NtTerminateThread(
- NtCurrentThread() ,
- uExitCode
- );
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- }
- return;
+ NTSTATUS Status;
+ Status = NtYieldExecution();
+ return Status != STATUS_NO_YIELD_PERFORMED;
}
-WINBOOL
-STDCALL
-GetThreadTimes(
- HANDLE hThread,
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCurrentThreadId(VOID)
+{
+ return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
+}
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetThreadTimes(HANDLE hThread,
LPFILETIME lpCreationTime,
LPFILETIME lpExitTime,
LPFILETIME lpKernelTime,
- LPFILETIME lpUserTime
- )
+ 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;
-
+ KERNEL_USER_TIMES KernelUserTimes;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadTimes,
+ &KernelUserTimes,
+ sizeof(KERNEL_USER_TIMES),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ 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;
+
+ return(TRUE);
}
-WINBOOL
-STDCALL GetThreadContext(
- HANDLE hThread,
- LPCONTEXT lpContext
- )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetThreadContext(HANDLE hThread,
+ LPCONTEXT lpContext)
{
- NTSTATUS errCode;
- errCode = NtGetContextThread(hThread,lpContext);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ NTSTATUS Status;
+
+ Status = NtGetContextThread(hThread,
+ lpContext);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ return(TRUE);
}
-WINBOOL
-STDCALL
-SetThreadContext(
- HANDLE hThread,
- CONST CONTEXT *lpContext
- )
+
+/*
+ * @implemented
+ */
+BOOL 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;
+ NTSTATUS Status;
+
+ Status = NtSetContextThread(hThread,
+ (void *)lpContext);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ return(TRUE);
}
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetExitCodeThread(HANDLE hThread,
+ LPDWORD lpExitCode)
+{
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
+
+ return(TRUE);
+}
-WINBOOL
-STDCALL
-GetExitCodeThread(
- HANDLE hThread,
- LPDWORD lpExitCode
- )
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+ResumeThread(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 FALSE;
- }
- memcpy( lpExitCode ,&ThreadBasic.ExitStatus,sizeof(DWORD));
- return TRUE;
-
+ ULONG PreviousResumeCount;
+ NTSTATUS Status;
+
+ Status = NtResumeThread(hThread,
+ &PreviousResumeCount);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(-1);
+ }
+
+ return(PreviousResumeCount);
}
-DWORD
-STDCALL
-ResumeThread(
- HANDLE hThread
- )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+TerminateThread(HANDLE hThread,
+ DWORD dwExitCode)
{
- NTSTATUS errCode;
- ULONG PreviousResumeCount;
-
- errCode = NtResumeThread(hThread,&PreviousResumeCount );
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return -1;
- }
- return PreviousResumeCount;
+ NTSTATUS Status;
+
+ if (0 == hThread)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ Status = NtTerminateThread(hThread,
+ dwExitCode);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ return(TRUE);
}
-DWORD
-STDCALL
-SuspendThread(
- HANDLE hThread
- )
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SuspendThread(HANDLE hThread)
{
- NTSTATUS errCode;
- ULONG PreviousSuspendCount;
-
- errCode = NtSuspendThread(hThread,&PreviousSuspendCount );
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return -1;
- }
- return PreviousSuspendCount;
+ ULONG PreviousSuspendCount;
+ NTSTATUS Status;
+
+ Status = NtSuspendThread(hThread,
+ &PreviousSuspendCount);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(-1);
+ }
+
+ return(PreviousSuspendCount);
}
-DWORD
-STDCALL
-SetThreadAffinityMask(
- HANDLE hThread,
- DWORD dwThreadAffinityMask
- )
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SetThreadAffinityMask(HANDLE hThread,
+ DWORD dwThreadAffinityMask)
{
- return 0;
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ KAFFINITY AffinityMask;
+ NTSTATUS Status;
+
+ AffinityMask = (KAFFINITY)dwThreadAffinityMask;
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(0);
+ }
+
+ Status = NtSetInformationThread(hThread,
+ ThreadAffinityMask,
+ &AffinityMask,
+ sizeof(KAFFINITY));
+ if (!NT_SUCCESS(Status))
+ SetLastErrorByStatus(Status);
+
+ return(ThreadBasic.AffinityMask);
}
-WINBOOL
-STDCALL
-SetThreadPriority(
- HANDLE hThread,
- int nPriority
- )
+/*
+ * @implemented
+ */
+BOOL 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;
+ ULONG Prio = nPriority;
+ NTSTATUS Status;
+
+ Status = NtSetInformationThread(hThread,
+ ThreadBasePriority,
+ &Prio,
+ sizeof(ULONG));
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ return(TRUE);
}
-int
-STDCALL
-GetThreadPriority(
- HANDLE hThread
- )
+/*
+ * @implemented
+ */
+int STDCALL
+GetThreadPriority(HANDLE hThread)
+{
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(THREAD_PRIORITY_ERROR_RETURN);
+ }
+
+ return(ThreadBasic.BasePriority);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetThreadPriorityBoost(IN HANDLE hThread,
+ OUT PBOOL pDisablePriorityBoost)
+{
+ ULONG PriorityBoost;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadPriorityBoost,
+ &PriorityBoost,
+ sizeof(ULONG),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ *pDisablePriorityBoost = !((BOOL)PriorityBoost);
+
+ return(TRUE);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetThreadPriorityBoost(IN HANDLE hThread,
+ IN BOOL bDisablePriorityBoost)
+{
+ ULONG PriorityBoost;
+ NTSTATUS Status;
+
+ PriorityBoost = (ULONG)!bDisablePriorityBoost;
+
+ Status = NtSetInformationThread(hThread,
+ ThreadPriorityBoost,
+ &PriorityBoost,
+ sizeof(ULONG));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetThreadSelectorEntry(IN HANDLE hThread,
+ IN DWORD dwSelector,
+ OUT LPLDT_ENTRY lpSelectorEntry)
+{
+ DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
+ NTSTATUS Status;
+
+ DescriptionTableEntry.Selector = dwSelector;
+ Status = NtQueryInformationThread(hThread,
+ ThreadDescriptorTableEntry,
+ &DescriptionTableEntry,
+ sizeof(DESCRIPTOR_TABLE_ENTRY),
+ NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+
+ *lpSelectorEntry = DescriptionTableEntry.Descriptor;
+ return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SetThreadIdealProcessor(HANDLE hThread,
+ DWORD dwIdealProcessor)
{
- 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;
+ NTSTATUS Status;
+
+ Status = NtSetInformationThread(hThread,
+ ThreadIdealProcessor,
+ &dwIdealProcessor,
+ sizeof(ULONG));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return -1;
+ }
+
+ return dwIdealProcessor;
}
-/* (WIN32) Thread Local Storage ******************************************** */
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetProcessIdOfThread(HANDLE Thread)
+{
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(Thread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return 0;
+ }
+
+ return (DWORD)ThreadBasic.ClientId.UniqueProcess;
+}
+
-DWORD STDCALL
-TlsAlloc(VOID)
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetThreadId(HANDLE Thread)
{
- DWORD dwTlsIndex = GetTeb()->dwTlsIndex;
-
-
- void **TlsData = GetTeb()->TlsData;
-
-
- if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
- {
- TlsData[dwTlsIndex] = NULL;
- return (dwTlsIndex++);
- }
- return (0xFFFFFFFFUL);
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationThread(Thread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return 0;
+ }
+
+ return (DWORD)ThreadBasic.ClientId.UniqueThread;
}
-WINBOOL STDCALL
-TlsFree(DWORD dwTlsIndex)
+/*
+ * @unimplemented
+ */
+LANGID STDCALL
+SetThreadUILanguage(WORD wReserved)
{
-
- return (TRUE);
+ DPRINT1("SetThreadUILanguage(0x%4x) unimplemented!\n", wReserved);
+ return 0;
}
-LPVOID STDCALL
-TlsGetValue(DWORD dwTlsIndex)
+static void CALLBACK
+IntCallUserApc(PVOID Function, PVOID dwData, PVOID Argument3)
{
-
-
- void **TlsData = GetTeb()->TlsData;
-
-
- if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
- {
-
- SetLastError(NO_ERROR);
- return (TlsData[dwTlsIndex]);
- }
- SetLastError(1);
- return (NULL);
+ PAPCFUNC pfnAPC = (PAPCFUNC)Function;
+ pfnAPC((ULONG_PTR)dwData);
}
-WINBOOL STDCALL
-TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
+/*
+ * @implemented
+ */
+DWORD STDCALL
+QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData)
+{
+ NTSTATUS Status;
+
+ Status = NtQueueApcThread(hThread, IntCallUserApc, pfnAPC,
+ (PVOID)dwData, NULL);
+ if (Status)
+ SetLastErrorByStatus(Status);
+
+ return NT_SUCCESS(Status);
+}
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetThreadIOPendingFlag(HANDLE hThread,
+ PBOOL lpIOIsPending)
+{
+ ULONG IoPending;
+ NTSTATUS Status;
+
+ if(lpIOIsPending == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ Status = NtQueryInformationThread(hThread,
+ ThreadIsIoPending,
+ (PVOID)&IoPending,
+ sizeof(IoPending),
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ *lpIOIsPending = ((IoPending != 0) ? TRUE : FALSE);
+ return TRUE;
+ }
+
+ SetLastErrorByStatus(Status);
+ return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+Sleep(DWORD dwMilliseconds)
+{
+ SleepEx(dwMilliseconds, FALSE);
+ return;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SleepEx(DWORD dwMilliseconds,
+ BOOL bAlertable)
{
-
-
- void **TlsData = GetTeb()->TlsData;
-
-
- if (dwTlsIndex < sizeof(TlsData) / sizeof(TlsData[0]))
- {
-
- TlsData[dwTlsIndex] = lpTlsValue;
- return (TRUE);
- }
- return (FALSE);
+ LARGE_INTEGER Interval;
+ NTSTATUS errCode;
+
+ if (dwMilliseconds != INFINITE)
+ {
+ /*
+ * System time units are 100 nanoseconds (a nanosecond is a billionth of
+ * a second).
+ */
+ Interval.QuadPart = -((ULONGLONG)dwMilliseconds * 10000);
+ }
+ else
+ {
+ /* Approximately 292000 years hence */
+ Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL;
+ }
+
+ errCode = NtDelayExecution ((bAlertable ? TRUE : FALSE), &Interval);
+ if (!NT_SUCCESS(errCode))
+ {
+ SetLastErrorByStatus (errCode);
+ return -1;
+ }
+ return 0;
}
-/*************************************************************/
+/* EOF */