update for HEAD-2003050101
[reactos.git] / lib / kernel32 / thread / thread.c
index f64a980..0000791 100644 (file)
 
 /* INCLUDES ******************************************************************/
 
-#include <windows.h>
-#include <kernel32/thread.h>
-#include <ntdll/ldr.h>
-#include <string.h>
-#include <napi/i386/segment.h>
+#include <k32.h>
 
 #define NDEBUG
 #include <kernel32/kernel32.h>
-#include <kernel32/error.h>
 
-
-static VOID ThreadAttachDlls (VOID);
+//static VOID ThreadAttachDlls (VOID);
 
 /* FUNCTIONS *****************************************************************/
 
-static\r
-EXCEPTION_DISPOSITION\r
-__cdecl\r
-_except_handler(\r
-    struct _EXCEPTION_RECORD *ExceptionRecord,\r
-    void * EstablisherFrame,\r
-    struct _CONTEXT *ContextRecord,\r
-    void * DispatcherContext )\r
-{\r
-       ExitThread(0);
-
-       /* We should not get to here */
-       return ExceptionContinueSearch;
-}\r
+/* FIXME: please put this in some header */
+static EXCEPTION_DISPOSITION __cdecl
+_except_handler(EXCEPTION_RECORD *ExceptionRecord,
+               void * EstablisherFrame,
+               CONTEXT *ContextRecord,
+               void * DispatcherContext)
+{
+  ExitThread(0);
+
+  /* We should not get to here */
+  return(ExceptionContinueSearch);
+}
+
 
 static VOID STDCALL
-ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
-               LPVOID lpParameter)
+ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
+             LPVOID lpParameter)
 {
-   UINT uExitCode;
+  UINT uExitCode;
+
+  __try1(_except_handler)
+  {
+    /* FIXME: notify csrss of thread creation ?? */
+    uExitCode = (lpStartAddress)(lpParameter);
+  }
+  __except1
+  {
+  }
+
+  ExitThread(uExitCode);
+}
 
-   __try1(_except_handler)
-   {
-               /* FIXME: notify csrss of thread creation ?? */
-               uExitCode = (lpStartAddress)(lpParameter);
-   } __except1
-   {
-   }
 
-   ExitThread(uExitCode);
+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 CreateThread(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
+)
 {
-   return(CreateRemoteThread(NtCurrentProcess(),
-                            lpThreadAttributes,
-                            dwStackSize,
-                            lpStartAddress,
-                            lpParameter,
-                            dwCreationFlags,
-                            lpThreadId));
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ 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;
 }
 
-HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
-                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                                 DWORD dwStackSize,
-                                 LPTHREAD_START_ROUTINE lpStartAddress,
-                                 LPVOID lpParameter,
-                                 DWORD dwCreationFlags,
-                                 LPDWORD lpThreadId)
+PTEB
+GetTeb(VOID)
 {
-   HANDLE ThreadHandle;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   CLIENT_ID ClientId;
-   CONTEXT ThreadContext;
-   INITIAL_TEB InitialTeb;
-   BOOLEAN CreateSuspended = FALSE;
-   PVOID BaseAddress;
-   ULONG OldPageProtection;
-   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;
-
-  InitialTeb.StackReserve = 0x100000; /* 1MByte */
-  /* FIXME: use correct commit size */
-#if 0
-  InitialTeb.StackCommit = (dwStackSize == 0) ? PAGE_SIZE : dwStackSize;
-#endif
-  InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
-
-  /* size of guard page */
-  InitialTeb.StackCommit += PAGE_SIZE;
-
-  /* Reserve stack */
-  InitialTeb.StackAllocate = NULL;
-  Status = NtAllocateVirtualMemory(hProcess,
-                                  &InitialTeb.StackAllocate,
-                                  0,
-                                  &InitialTeb.StackReserve,
-                                  MEM_RESERVE,
-                                  PAGE_READWRITE);
-  if (!NT_SUCCESS(Status))
+  return(NtCurrentTeb());
+}
+
+
+WINBOOL STDCALL
+SwitchToThread(VOID)
+{
+  NTSTATUS errCode;
+  errCode = NtYieldExecution();
+  return TRUE;
+}
+
+
+DWORD STDCALL
+GetCurrentThreadId(VOID)
+{
+  return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
+}
+
+
+VOID STDCALL
+ExitThread(DWORD uExitCode)
+{
+  BOOLEAN LastThread;
+  NTSTATUS Status;
+
+  /*
+   * 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)
     {
-      DPRINT("Error reserving stack space!\n");
-      SetLastErrorByStatus(Status);
-      return(NULL);
+      ExitProcess(uExitCode);
     }
 
-  DPRINT("StackDeallocation: %p ReserveSize: 0x%lX\n",
-        InitialTeb.StackDeallocation, InitialTeb.StackReserve);
+  /* FIXME: notify csrss of thread termination */
 
-  InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
-  InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
+  LdrShutdownThread();
 
-  DPRINT("StackBase: %p\nStackCommit: 0x%lX\n",
-        InitialTeb.StackBase,
-        InitialTeb.StackCommit);
-
-  /* Commit stack pages */
-  Status = NtAllocateVirtualMemory(hProcess,
-                                  &InitialTeb.StackLimit,
-                                  0,
-                                  &InitialTeb.StackCommit,
-                                  MEM_COMMIT,
-                                  PAGE_READWRITE);
+  Status = NtTerminateThread(NtCurrentThread(),
+                            uExitCode);
   if (!NT_SUCCESS(Status))
     {
-      /* release the stack space */
-      NtFreeVirtualMemory(hProcess,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("Error comitting stack page(s)!\n");
       SetLastErrorByStatus(Status);
-      return(NULL);
     }
+}
 
-  DPRINT("StackLimit: %p\n",
-        InitialTeb.StackLimit);
 
-  /* Protect guard page */
-  Status = NtProtectVirtualMemory(hProcess,
-                                 InitialTeb.StackLimit,
-                                 PAGE_SIZE,
-                                 PAGE_GUARD | PAGE_READWRITE,
-                                 &OldPageProtection);
+WINBOOL STDCALL
+GetThreadTimes(HANDLE hThread,
+              LPFILETIME lpCreationTime,
+              LPFILETIME lpExitTime,
+              LPFILETIME lpKernelTime,
+              LPFILETIME lpUserTime)
+{
+  KERNEL_USER_TIMES KernelUserTimes;
+  ULONG ReturnLength;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationThread(hThread,
+                                   ThreadTimes,
+                                   &KernelUserTimes,
+                                   sizeof(KERNEL_USER_TIMES),
+                                   &ReturnLength);
   if (!NT_SUCCESS(Status))
     {
-      /* release the stack space */
-      NtFreeVirtualMemory(hProcess,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("Error comitting guard page!\n");
       SetLastErrorByStatus(Status);
-      return(NULL);
+      return(FALSE);
     }
 
-  memset(&ThreadContext,0,sizeof(CONTEXT));
-  ThreadContext.Eip = (LONG)ThreadStartup;
-  ThreadContext.SegGs = USER_DS;
-  ThreadContext.SegFs = TEB_SELECTOR;
-  ThreadContext.SegEs = USER_DS;
-  ThreadContext.SegDs = USER_DS;
-  ThreadContext.SegCs = USER_CS;
-  ThreadContext.SegSs = USER_DS;
-  ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 12;
-  ThreadContext.EFlags = (1<<1) + (1<<9);
-
-  /* initialize call stack */
-  *((PULONG)((ULONG)InitialTeb.StackBase - 4)) = (ULONG)lpParameter;
-  *((PULONG)((ULONG)InitialTeb.StackBase - 8)) = (ULONG)lpStartAddress;
-  *((PULONG)((ULONG)InitialTeb.StackBase - 12)) = 0xdeadbeef;
-
-  DPRINT("Esp: %p\n", ThreadContext.Esp);
-  DPRINT("Eip: %p\n", ThreadContext.Eip);
-
-  Status = NtCreateThread(&ThreadHandle,
-                         THREAD_ALL_ACCESS,
-                         &ObjectAttributes,
-                         hProcess,
-                         &ClientId,
-                         &ThreadContext,
-                         &InitialTeb,
-                         CreateSuspended);
+  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 Status;
+
+  Status = NtGetContextThread(hThread,
+                             lpContext);
   if (!NT_SUCCESS(Status))
     {
-      NtFreeVirtualMemory(hProcess,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("NtCreateThread() failed!\n");
       SetLastErrorByStatus(Status);
-      return(NULL);
+      return(FALSE);
     }
 
-  if (lpThreadId != NULL)
-    memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
-
-  return(ThreadHandle);
+  return(TRUE);
 }
 
-PTEB
-GetTeb(VOID)
+
+WINBOOL STDCALL
+SetThreadContext(HANDLE hThread,
+                CONST CONTEXT *lpContext)
 {
-  return(NtCurrentTeb());
+  NTSTATUS Status;
+
+  Status = NtSetContextThread(hThread,
+                             (void *)lpContext);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
+
 WINBOOL STDCALL
-SwitchToThread(VOID)
+GetExitCodeThread(HANDLE hThread,
+                 LPDWORD lpExitCode)
 {
-   NTSTATUS errCode;
-   errCode = NtYieldExecution();
-   return TRUE;
+  THREAD_BASIC_INFORMATION ThreadBasic;
+  ULONG DataWritten;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationThread(hThread,
+                                   ThreadBasicInformation,
+                                   &ThreadBasic,
+                                   sizeof(THREAD_BASIC_INFORMATION),
+                                   &DataWritten);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
+
+  return(TRUE);
 }
 
+
 DWORD STDCALL
-GetCurrentThreadId()
+ResumeThread(HANDLE hThread)
 {
-   return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
-}
+  ULONG PreviousResumeCount;
+  NTSTATUS Status;
 
-VOID STDCALL
-ExitThread(DWORD uExitCode)
-{
-   NTSTATUS errCode;
-   BOOLEAN LastThread;
-   NTSTATUS Status;
-
-   /*
-    * 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();
-
-   errCode = NtTerminateThread(NtCurrentThread(),
-                              uExitCode);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-     }
-}
+  Status = NtResumeThread(hThread,
+                         &PreviousResumeCount);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(-1);
+    }
 
-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))
-     {
-       SetLastErrorByStatus(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;
+  return(PreviousResumeCount);
 }
 
 
-WINBOOL STDCALL GetThreadContext(HANDLE hThread,
-                                LPCONTEXT lpContext)
+WINBOOL STDCALL
+TerminateThread(HANDLE hThread,
+               DWORD dwExitCode)
 {
-   NTSTATUS errCode;
-   
-   errCode = NtGetContextThread(hThread,
-                               lpContext);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return FALSE;
-     }
-   return TRUE;
-}
+  NTSTATUS Status;
 
-WINBOOL STDCALL SetThreadContext(HANDLE hThread,
-                                CONST CONTEXT *lpContext)
-{
-   NTSTATUS errCode;
-   
-   errCode = NtSetContextThread(hThread,
-                               (void *)lpContext);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return FALSE;
-     }
-   return TRUE;
+  if (0 == hThread)
+    {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return(FALSE);
+    }
+
+  Status = NtTerminateThread(hThread,
+                            dwExitCode);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
-WINBOOL STDCALL GetExitCodeThread(HANDLE hThread,
-                                 LPDWORD lpExitCode)
+
+DWORD STDCALL
+SuspendThread(HANDLE hThread)
 {
-   NTSTATUS errCode;
-   THREAD_BASIC_INFORMATION ThreadBasic;
-   ULONG DataWritten;
-   
-   errCode = NtQueryInformationThread(hThread,
-                                     ThreadBasicInformation,
-                                     &ThreadBasic,
-                                     sizeof(THREAD_BASIC_INFORMATION),
-                                     &DataWritten);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return FALSE;
-     }
-   memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
-   return TRUE;
+  ULONG PreviousSuspendCount;
+  NTSTATUS Status;
+
+  Status = NtSuspendThread(hThread,
+                          &PreviousSuspendCount);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(-1);
+    }
+
+  return(PreviousSuspendCount);
 }
 
-DWORD STDCALL ResumeThread(HANDLE hThread)
+
+DWORD STDCALL
+SetThreadAffinityMask(HANDLE hThread,
+                     DWORD dwThreadAffinityMask)
 {
-   NTSTATUS errCode;
-   ULONG PreviousResumeCount;
-   
-   errCode = NtResumeThread(hThread,
-                           &PreviousResumeCount);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return  -1;
-     }
-   return PreviousResumeCount;
+  THREAD_BASIC_INFORMATION ThreadBasic;
+  KAFFINITY AffinityMask;
+  ULONG DataWritten;
+  NTSTATUS Status;
+
+  AffinityMask = (KAFFINITY)dwThreadAffinityMask;
+
+  Status = NtQueryInformationThread(hThread,
+                                   ThreadBasicInformation,
+                                   &ThreadBasic,
+                                   sizeof(THREAD_BASIC_INFORMATION),
+                                   &DataWritten);
+  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
-TerminateThread (HANDLE        hThread,
-                DWORD  dwExitCode)
+SetThreadPriority(HANDLE hThread,
+                 int nPriority)
 {
-    if (0 == hThread)
+  ULONG Prio = nPriority;
+  NTSTATUS Status;
+
+  Status = NtSetInformationThread(hThread,
+                                 ThreadBasePriority,
+                                 &Prio,
+                                 sizeof(ULONG));
+
+  if (!NT_SUCCESS(Status))
     {
-        SetLastError (ERROR_INVALID_HANDLE);
+      SetLastErrorByStatus(Status);
+      return(FALSE);
     }
-    else
+
+  return(TRUE);
+}
+
+
+int STDCALL
+GetThreadPriority(HANDLE hThread)
+{
+  THREAD_BASIC_INFORMATION ThreadBasic;
+  ULONG DataWritten;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationThread(hThread,
+                                   ThreadBasicInformation,
+                                   &ThreadBasic,
+                                   sizeof(THREAD_BASIC_INFORMATION),
+                                   &DataWritten);
+  if (!NT_SUCCESS(Status))
     {
-        NTSTATUS Status = NtTerminateThread (hThread, dwExitCode);
-       
-        if (NT_SUCCESS(Status))
-       {
-            return TRUE;
-        }
-        SetLastErrorByStatus (Status);
+      SetLastErrorByStatus(Status);
+      return(THREAD_PRIORITY_ERROR_RETURN);
     }
-    return FALSE;
+
+  return(ThreadBasic.BasePriority);
 }
 
 
-DWORD STDCALL SuspendThread(HANDLE hThread)
+WINBOOL STDCALL
+GetThreadPriorityBoost(IN HANDLE hThread,
+                      OUT PBOOL pDisablePriorityBoost)
 {
-   NTSTATUS errCode;
-   ULONG PreviousSuspendCount;
-   
-   errCode = NtSuspendThread(hThread,
-                            &PreviousSuspendCount);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return -1;
-     }
-   return PreviousSuspendCount;
+  ULONG PriorityBoost;
+  ULONG DataWritten;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationThread(hThread,
+                                   ThreadPriorityBoost,
+                                   &PriorityBoost,
+                                   sizeof(ULONG),
+                                   &DataWritten);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  *pDisablePriorityBoost = !((WINBOOL)PriorityBoost);
+
+  return(TRUE);
 }
 
-DWORD STDCALL SetThreadAffinityMask(HANDLE hThread,
-                                   DWORD dwThreadAffinityMask)
+
+WINBOOL STDCALL
+SetThreadPriorityBoost(IN HANDLE hThread,
+                      IN WINBOOL bDisablePriorityBoost)
 {
-   return 0;
+  ULONG PriorityBoost;
+  NTSTATUS Status;
+
+  PriorityBoost = (ULONG)!bDisablePriorityBoost;
+
+  Status = NtSetInformationThread(hThread,
+                                 ThreadPriorityBoost,
+                                 &PriorityBoost,
+                                 sizeof(ULONG));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
-WINBOOL STDCALL SetThreadPriority(HANDLE hThread,
-                                 int nPriority)
+
+WINBOOL STDCALL
+GetThreadSelectorEntry(IN HANDLE hThread,
+                      IN DWORD dwSelector,
+                      OUT LPLDT_ENTRY lpSelectorEntry)
 {
-   NTSTATUS errCode;
-   THREAD_BASIC_INFORMATION ThreadBasic;
-   ULONG DataWritten;
-   
-   errCode = NtQueryInformationThread(hThread,
-                                     ThreadBasicInformation,
-                                     &ThreadBasic,
-                                     sizeof(THREAD_BASIC_INFORMATION),
-                                     &DataWritten);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return FALSE;
-     }
-   ThreadBasic.BasePriority = nPriority;
-   errCode = NtSetInformationThread(hThread,
-                                   ThreadBasicInformation,
-                                   &ThreadBasic,
-                                   sizeof(THREAD_BASIC_INFORMATION));
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastErrorByStatus(errCode);
-       return FALSE;
-     }
-   return TRUE;
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return(FALSE);
 }
 
-int STDCALL GetThreadPriority(HANDLE hThread)
+
+WINBOOL 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))
-     {
-       SetLastErrorByStatus(errCode);
-       return THREAD_PRIORITY_ERROR_RETURN;
-     }
-   return ThreadBasic.BasePriority;
+  ULONG IdealProcessor;
+  NTSTATUS Status;
+
+  IdealProcessor = (ULONG)dwIdealProcessor;
+
+  Status = NtSetInformationThread(hThread,
+                                 ThreadIdealProcessor,
+                                 &IdealProcessor,
+                                 sizeof(ULONG));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
 /* EOF */