branch update for HEAD-2003050101
[reactos.git] / lib / kernel32 / thread / thread.c
index e4a9423..0000791 100644 (file)
 #define NDEBUG
 #include <kernel32/kernel32.h>
 
-
 //static VOID ThreadAttachDlls (VOID);
 
 /* FUNCTIONS *****************************************************************/
 
+/* FIXME: please put this in some header */
 static EXCEPTION_DISPOSITION __cdecl
-_except_handler(struct _EXCEPTION_RECORD *ExceptionRecord,
+_except_handler(EXCEPTION_RECORD *ExceptionRecord,
                void * EstablisherFrame,
-               struct _CONTEXT *ContextRecord,
+               CONTEXT *ContextRecord,
                void * DispatcherContext)
 {
   ExitThread(0);
@@ -54,184 +54,190 @@ ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
 }
 
 
-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));
+ 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 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;
-  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;
+ 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
-  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))
-    {
-      DPRINT("Error reserving stack space!\n");
-      SetLastErrorByStatus(Status);
-      return(NULL);
-    }
-
-  DPRINT("StackDeallocation: %p ReserveSize: 0x%lX\n",
-        InitialTeb.StackDeallocation, InitialTeb.StackReserve);
-
-  InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
-  InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
 
-  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);
-  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);
-  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);
-    }
-
-  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);
-  if (!NT_SUCCESS(Status))
-    {
-      NtFreeVirtualMemory(hProcess,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("NtCreateThread() failed!\n");
-      SetLastErrorByStatus(Status);
-      return(NULL);
-    }
-
-  if (lpThreadId != NULL)
-    memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
-
-  return(ThreadHandle);
+ /* 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;
 }
 
-
 PTEB
 GetTeb(VOID)
 {
@@ -477,27 +483,14 @@ WINBOOL STDCALL
 SetThreadPriority(HANDLE hThread,
                  int nPriority)
 {
-  THREAD_BASIC_INFORMATION ThreadBasic;
-  ULONG DataWritten;
+  ULONG Prio = nPriority;
   NTSTATUS Status;
 
-  Status = NtQueryInformationThread(hThread,
-                                   ThreadBasicInformation,
-                                   &ThreadBasic,
-                                   sizeof(THREAD_BASIC_INFORMATION),
-                                   &DataWritten);
-  if (!NT_SUCCESS(Status))
-    {
-      SetLastErrorByStatus(Status);
-      return(FALSE);
-    }
-
-  ThreadBasic.BasePriority = nPriority;
-
   Status = NtSetInformationThread(hThread,
-                                 ThreadBasicInformation,
-                                 &ThreadBasic,
-                                 sizeof(THREAD_BASIC_INFORMATION));
+                                 ThreadBasePriority,
+                                 &Prio,
+                                 sizeof(ULONG));
+
   if (!NT_SUCCESS(Status))
     {
       SetLastErrorByStatus(Status);