update for HEAD-2003050101
[reactos.git] / lib / kernel32 / process / create.c
index 776057c..f871c97 100644 (file)
 
 /* FUNCTIONS ****************************************************************/
 
-WINBOOL STDCALL
-CreateProcessA (LPCSTR                 lpApplicationName,
-               LPSTR                   lpCommandLine,
-               LPSECURITY_ATTRIBUTES   lpProcessAttributes,
-               LPSECURITY_ATTRIBUTES   lpThreadAttributes,
-               WINBOOL                 bInheritHandles,
-               DWORD                   dwCreationFlags,
-               LPVOID                  lpEnvironment,
-               LPCSTR                  lpCurrentDirectory,
-               LPSTARTUPINFOA          lpStartupInfo,
-               LPPROCESS_INFORMATION   lpProcessInformation)
+__declspec(dllimport)
+PRTL_BASE_PROCESS_START_ROUTINE RtlBaseProcessStartRoutine;
+
+typedef NTSTATUS STDCALL (K32_MBSTR_TO_WCSTR)
+(
+ UNICODE_STRING *,
+ ANSI_STRING *,
+ BOOLEAN
+);
+
+NTSTATUS STDCALL K32MbStrToWcStr
+(
+ IN K32_MBSTR_TO_WCSTR * True,
+ UNICODE_STRING * DestStr,
+ ANSI_STRING * SourceStr,
+ BOOLEAN Allocate
+)
+{
+ if(SourceStr->Buffer == NULL)
+ {
+  DestStr->Length = DestStr->MaximumLength = 0;
+  DestStr->Buffer = NULL;
+  return STATUS_SUCCESS;
+ }
+
+ return True(DestStr, SourceStr, Allocate);
+}
+
+VOID STDCALL RtlRosR32AttribsToNativeAttribs
+(
+ OUT OBJECT_ATTRIBUTES * NativeAttribs,
+ IN SECURITY_ATTRIBUTES * Ros32Attribs OPTIONAL
+)
+{
+ NativeAttribs->Length = sizeof(*NativeAttribs);
+ NativeAttribs->ObjectName = NULL;
+ NativeAttribs->RootDirectory = NULL;
+ NativeAttribs->Attributes = 0;
+ NativeAttribs->SecurityQualityOfService = NULL;
+
+ if(Ros32Attribs != NULL && Ros32Attribs->nLength >= sizeof(*Ros32Attribs))
+ {
+  NativeAttribs->SecurityDescriptor = Ros32Attribs->lpSecurityDescriptor;
+  
+  if(Ros32Attribs->bInheritHandle)
+   NativeAttribs->Attributes |= OBJ_INHERIT;
+ }
+ else
+  NativeAttribs->SecurityDescriptor = NULL;
+}
+
+VOID STDCALL RtlRosR32AttribsToNativeAttribsNamed
+(
+ OUT OBJECT_ATTRIBUTES * NativeAttribs,
+ IN SECURITY_ATTRIBUTES * Ros32Attribs OPTIONAL,
+ OUT UNICODE_STRING * NativeName OPTIONAL,
+ IN WCHAR * Ros32Name OPTIONAL,
+ IN HANDLE Ros32NameRoot OPTIONAL
+)
+{
+ if(!NativeAttribs) return;
+
+ RtlRosR32AttribsToNativeAttribs(NativeAttribs, Ros32Attribs);
+
+ if(Ros32Name != NULL && NativeName != NULL)
+ {
+  RtlInitUnicodeString(NativeName, Ros32Name);
+
+  NativeAttribs->ObjectName = NativeName;
+  NativeAttribs->RootDirectory = Ros32NameRoot;
+  NativeAttribs->Attributes |= OBJ_CASE_INSENSITIVE;
+ }
+}
+
+BOOL STDCALL CreateProcessA
+(
+ LPCSTR lpApplicationName,
+ LPSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCSTR lpCurrentDirectory,
+ LPSTARTUPINFOA lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation
+)
 /*
  * FUNCTION: The CreateProcess function creates a new process and its
  * primary thread. The new process executes the specified executable file
@@ -46,112 +123,185 @@ CreateProcessA (LPCSTR                   lpApplicationName,
  *     lpProcessInformation = Pointer to process information
  */
 {
-       PWCHAR lpEnvironmentW = NULL;
-       UNICODE_STRING ApplicationNameU;
-       UNICODE_STRING CurrentDirectoryU;
-       UNICODE_STRING CommandLineU;
-       ANSI_STRING ApplicationName;
-       ANSI_STRING CurrentDirectory;
-       ANSI_STRING CommandLine;
-       WINBOOL Result;
-       CHAR TempCurrentDirectoryA[256];
-
-       DPRINT("CreateProcessA(%s)\n", lpApplicationName);
-       DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, "
-               "lpStartupInfo %x, lpProcessInformation %x\n", dwCreationFlags, 
-               lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
-
-       if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT))
-       {
-               PCHAR ptr = lpEnvironment;
-               ULONG len = 0;
-               UNICODE_STRING EnvironmentU;
-               ANSI_STRING EnvironmentA;
-               while (*ptr)
-               {
-                       RtlInitAnsiString(&EnvironmentA, ptr);
-                       if (bIsFileApiAnsi)
-                               len += RtlAnsiStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR);
-                       else
-                               len += RtlOemStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR);
-                       ptr += EnvironmentA.MaximumLength;
-               }
-               len += sizeof(WCHAR);
-               lpEnvironmentW = (PWCHAR)RtlAllocateHeap(GetProcessHeap(),
-                                                        HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, 
-                                                        len);
-               if (lpEnvironmentW == NULL)
-               {
-                       return FALSE;
-               }
-               ptr = lpEnvironment;
-               EnvironmentU.Buffer = lpEnvironmentW;
-               EnvironmentU.Length = 0;
-               EnvironmentU.MaximumLength = len;
-               while (*ptr)
-               {
-                       RtlInitAnsiString(&EnvironmentA, ptr);
-                       if (bIsFileApiAnsi)
-                               RtlAnsiStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE);
-                       else
-                               RtlOemStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE);
-                       ptr += EnvironmentA.MaximumLength;
-                       EnvironmentU.Buffer += (EnvironmentU.Length / sizeof(WCHAR) + 1);
-                       EnvironmentU.MaximumLength -= (EnvironmentU.Length + sizeof(WCHAR));
-                       EnvironmentU.Length = 0;
-               }
-
-               EnvironmentU.Buffer[0] = 0;     
-       }
-    
-       RtlInitAnsiString (&CommandLine,
-                          lpCommandLine);
-       RtlInitAnsiString (&ApplicationName,
-                          (LPSTR)lpApplicationName);
-       if (lpCurrentDirectory != NULL)
-         {
-           RtlInitAnsiString (&CurrentDirectory,
-                              (LPSTR)lpCurrentDirectory);
-         }
-
-       /* convert ansi (or oem) strings to unicode */
-       if (bIsFileApiAnsi)
-       {
-               RtlAnsiStringToUnicodeString (&CommandLineU, &CommandLine, TRUE);
-               RtlAnsiStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE);
-               if (lpCurrentDirectory != NULL)
-                       RtlAnsiStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE);
-       }
-       else
-       {
-               RtlOemStringToUnicodeString (&CommandLineU, &CommandLine, TRUE);
-               RtlOemStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE);
-               if (lpCurrentDirectory != NULL)  
-                       RtlOemStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE);
-       }
-
-       Result = CreateProcessW (ApplicationNameU.Buffer,
-                                CommandLineU.Buffer,
-                                lpProcessAttributes,
-                                lpThreadAttributes,
-                                bInheritHandles,
-                                dwCreationFlags,
-                                dwCreationFlags & CREATE_UNICODE_ENVIRONMENT ? lpEnvironment : lpEnvironmentW,
-                                (lpCurrentDirectory == NULL) ? NULL : CurrentDirectoryU.Buffer,
-                                (LPSTARTUPINFOW)lpStartupInfo,
-                                lpProcessInformation);
-
-       RtlFreeUnicodeString (&ApplicationNameU);
-       RtlFreeUnicodeString (&CommandLineU);
-       if (lpCurrentDirectory != NULL)
-               RtlFreeUnicodeString (&CurrentDirectoryU);
-
-       if (lpEnvironmentW)
-       {
-               RtlFreeHeap(GetProcessHeap(), 0, lpEnvironmentW);
-       }
-
-       return Result;
+ PWCHAR pwcEnv = NULL;
+ UNICODE_STRING wstrApplicationName;
+ UNICODE_STRING wstrCurrentDirectory;
+ UNICODE_STRING wstrCommandLine;
+ UNICODE_STRING wstrReserved;
+ UNICODE_STRING wstrDesktop;
+ UNICODE_STRING wstrTitle;
+ ANSI_STRING strApplicationName;
+ ANSI_STRING strCurrentDirectory;
+ ANSI_STRING strCommandLine;
+ ANSI_STRING strReserved;
+ ANSI_STRING strDesktop;
+ ANSI_STRING strTitle;
+ BOOL bRetVal;
+ STARTUPINFOW wsiStartupInfo;
+
+ NTSTATUS STDCALL (*pTrue)
+ (
+  UNICODE_STRING *,
+  ANSI_STRING *,
+  BOOLEAN
+ );
+
+ ULONG STDCALL (*pRtlMbStringToUnicodeSize)(ANSI_STRING *);
+
+ DPRINT("CreateProcessA(%s)\n", lpApplicationName);
+
+ DPRINT
+ (
+   "dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, "
+   "lpStartupInfo %x, lpProcessInformation %x\n",
+  dwCreationFlags, 
+  lpEnvironment,
+  lpCurrentDirectory,
+  lpStartupInfo,
+  lpProcessInformation
+ );
+
+ /* invalid parameter */
+ if(lpStartupInfo == NULL)
+ {
+  SetLastError(ERROR_INVALID_PARAMETER);
+  return FALSE;
+ }
+
+ /* multibyte strings are ANSI */
+ if(bIsFileApiAnsi)
+ {
+  pTrue = RtlAnsiStringToUnicodeString;
+  pRtlMbStringToUnicodeSize = RtlAnsiStringToUnicodeSize;
+ }
+ /* multibyte strings are OEM */
+ else
+ {
+  pTrue = RtlOemStringToUnicodeString;
+  pRtlMbStringToUnicodeSize = RtlOemStringToUnicodeSize;
+ }
+
+ /* convert the environment */
+ if(lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT))
+ {
+  PCHAR pcScan;
+  SIZE_T nEnvLen = 0;
+  UNICODE_STRING wstrEnvVar;
+  ANSI_STRING strEnvVar;
+
+  /* scan the environment to calculate its Unicode size */
+  for(pcScan = lpEnvironment; *pcScan; pcScan += strEnvVar.MaximumLength)
+  {
+   /* add the size of the current variable */
+   RtlInitAnsiString(&strEnvVar, pcScan);
+   nEnvLen += pRtlMbStringToUnicodeSize(&strEnvVar) + sizeof(WCHAR);
+  }
+
+  /* add the size of the final NUL character */
+  nEnvLen += sizeof(WCHAR);
+
+  /* environment too large */
+  if(nEnvLen > ~((USHORT)0))
+  {
+   SetLastError(ERROR_OUTOFMEMORY);
+   return FALSE;
+  }
+
+  /* allocate the Unicode environment */
+  pwcEnv = (PWCHAR)RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, nEnvLen);
+
+  /* failure */
+  if(pwcEnv == NULL)
+  {
+   SetLastError(ERROR_OUTOFMEMORY);
+   return FALSE;
+  }
+
+  wstrEnvVar.Buffer = pwcEnv;
+  wstrEnvVar.Length = 0;
+  wstrEnvVar.MaximumLength = nEnvLen;
+
+  /* scan the environment to convert it */
+  for(pcScan = lpEnvironment; *pcScan; pcScan += strEnvVar.MaximumLength)
+  {
+   /* convert the current variable */
+   RtlInitAnsiString(&strEnvVar, pcScan);
+   K32MbStrToWcStr(pTrue, &wstrEnvVar, &strEnvVar, FALSE);
+
+   /* advance the buffer to the next variable */
+   wstrEnvVar.Buffer += (wstrEnvVar.Length / sizeof(WCHAR) + 1);
+   wstrEnvVar.MaximumLength -= (wstrEnvVar.Length + sizeof(WCHAR));
+   wstrEnvVar.Length = 0;
+  }
+
+  /* final NUL character */
+  wstrEnvVar.Buffer[0] = 0;    
+ }
+
+ /* convert the strings */
+ RtlInitAnsiString(&strCommandLine, lpCommandLine);
+ RtlInitAnsiString(&strApplicationName, (LPSTR)lpApplicationName);
+ RtlInitAnsiString(&strCurrentDirectory, (LPSTR)lpCurrentDirectory);
+ RtlInitAnsiString(&strReserved, (LPSTR)lpStartupInfo->lpReserved);
+ RtlInitAnsiString(&strDesktop, (LPSTR)lpStartupInfo->lpDesktop);
+ RtlInitAnsiString(&strTitle, (LPSTR)lpStartupInfo->lpTitle);
+
+ K32MbStrToWcStr(pTrue, &wstrCommandLine, &strCommandLine, TRUE);
+ K32MbStrToWcStr(pTrue, &wstrApplicationName, &strApplicationName, TRUE);
+ K32MbStrToWcStr(pTrue, &wstrCurrentDirectory, &strCurrentDirectory, TRUE);
+ K32MbStrToWcStr(pTrue, &wstrReserved, &strReserved, TRUE);
+ K32MbStrToWcStr(pTrue, &wstrDesktop, &strDesktop, TRUE);
+ K32MbStrToWcStr(pTrue, &wstrTitle, &strTitle, TRUE);
+
+ /* convert the startup information */
+ memcpy(&wsiStartupInfo, lpStartupInfo, sizeof(wsiStartupInfo));
+
+ wsiStartupInfo.lpReserved = wstrReserved.Buffer;
+ wsiStartupInfo.lpDesktop = wstrDesktop.Buffer;
+ wsiStartupInfo.lpTitle = wstrTitle.Buffer;
+
+ DPRINT("wstrApplicationName  %wZ\n", &wstrApplicationName);
+ DPRINT("wstrCommandLine      %wZ\n", &wstrCommandLine);
+ DPRINT("wstrCurrentDirectory %wZ\n", &wstrCurrentDirectory);
+ DPRINT("wstrReserved         %wZ\n", &wstrReserved);
+ DPRINT("wstrDesktop          %wZ\n", &wstrDesktop);
+ DPRINT("wstrTitle            %wZ\n", &wstrTitle);
+
+ DPRINT("wstrApplicationName.Buffer  %p\n", wstrApplicationName.Buffer);
+ DPRINT("wstrCommandLine.Buffer      %p\n", wstrCommandLine.Buffer);
+ DPRINT("wstrCurrentDirectory.Buffer %p\n", wstrCurrentDirectory.Buffer);
+ DPRINT("wstrReserved.Buffer         %p\n", wstrReserved.Buffer);
+ DPRINT("wstrDesktop.Buffer          %p\n", wstrDesktop.Buffer);
+ DPRINT("wstrTitle.Buffer            %p\n", wstrTitle.Buffer);
+
+ DPRINT("sizeof(STARTUPINFOA) %lu\n", sizeof(STARTUPINFOA));
+ DPRINT("sizeof(STARTUPINFOW) %lu\n", sizeof(STARTUPINFOW));
+
+ /* call the Unicode function */
+ bRetVal = CreateProcessW
+ (
+  wstrApplicationName.Buffer,
+  wstrCommandLine.Buffer,
+  lpProcessAttributes,
+  lpThreadAttributes,
+  bInheritHandles,
+  dwCreationFlags,
+  dwCreationFlags & CREATE_UNICODE_ENVIRONMENT ? lpEnvironment : pwcEnv,
+  wstrCurrentDirectory.Buffer,
+  &wsiStartupInfo,
+  lpProcessInformation
+ );
+
+ RtlFreeUnicodeString(&wstrApplicationName);
+ RtlFreeUnicodeString(&wstrCommandLine);
+ RtlFreeUnicodeString(&wstrCurrentDirectory);
+ RtlFreeUnicodeString(&wstrReserved);
+ RtlFreeUnicodeString(&wstrDesktop);
+ RtlFreeUnicodeString(&wstrTitle);
+
+ RtlFreeHeap(GetProcessHeap(), 0, pwcEnv);
+
+ return bRetVal;
 }
 
 static int _except_recursion_trap = 0;
@@ -168,29 +318,32 @@ _except_handler(
     struct _CONTEXT *ContextRecord,
     void * DispatcherContext )
 {
      DPRINT("Process terminated abnormally...\n");
DPRINT1("Process terminated abnormally due to unhandled exception\n");
 
-       if (++_except_recursion_trap > 3) {
-        DPRINT("_except_handler(...) appears to be recursing.\n");
-        DPRINT("Process HALTED.\n");
-               for (;;) {}
-       }
-
-       if (/* FIXME: */ TRUE) /* Not a service */
-       {
-        DPRINT("  calling ExitProcess(0) no, lets try ExitThread . . .\n");
-               //ExitProcess(0);
-               ExitThread(0);
-       }
-       else
+ if (3 < ++_except_recursion_trap)
+    {
+      DPRINT1("_except_handler(...) appears to be recursing.\n");
+      DPRINT1("Process HALTED.\n");
+      for (;;)
        {
-        DPRINT("  calling ExitThread(0) . . .\n");
-               ExitThread(0);
        }
+    }
 
-    DPRINT("  We should not get to here !!!\n");
-       /* We should not get to here */
-       return ExceptionContinueSearch;
+  if (/* FIXME: */ TRUE) /* Not a service */
+    {
+      DPRINT("  calling ExitProcess(0) no, lets try ExitThread . . .\n");
+      /* ExitProcess(0); */
+      ExitThread(0);
+    }
+  else
+    {
+    DPRINT("  calling ExitThread(0) . . .\n");
+    ExitThread(0);
+    }
+
+  DPRINT1("  We should not get to here !!!\n");
+  /* We should not get to here */
+  return ExceptionContinueSearch;
 }
 
 VOID STDCALL
@@ -199,7 +352,7 @@ BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress,
 {
        UINT uExitCode = 0;
 
-    DPRINT("\nBaseProcessStart(..) - setting up exception frame.\n\n");
+    DPRINT("BaseProcessStart(..) - setting up exception frame.\n");
 
        __try1(_except_handler)
        {
@@ -208,185 +361,111 @@ BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress,
        {
        }
 
-    DPRINT("\nBaseProcessStart(..) - cleaned up exception frame.\n\n");
+    DPRINT("BaseProcessStart(..) - cleaned up exception frame.\n");
 
        ExitThread(uExitCode);
 }
 
 
-HANDLE STDCALL 
-KlCreateFirstThread(HANDLE ProcessHandle,
-                   LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                   ULONG StackReserve,
-                   ULONG StackCommit,
-                   LPTHREAD_START_ROUTINE lpStartAddress,
-                   DWORD dwCreationFlags,
-                   LPDWORD lpThreadId)
+HANDLE STDCALL KlCreateFirstThread
+(
+ HANDLE ProcessHandle,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ PSECTION_IMAGE_INFORMATION Sii,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId
+)
 {
-  NTSTATUS Status;
-  HANDLE ThreadHandle;
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  CLIENT_ID ClientId;
-  CONTEXT ThreadContext;
-  INITIAL_TEB InitialTeb;
-  BOOLEAN CreateSuspended = FALSE;
-  ULONG OldPageProtection;
-  ULONG ResultLength;
-  ULONG InitialStack[6];
-
-  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 = (StackReserve < 0x100000) ? 0x100000 : StackReserve;
-  /* FIXME: use correct commit size */
-#if 0
-  InitialTeb.StackCommit = (StackCommit < PAGE_SIZE) ? PAGE_SIZE : StackCommit;
-#endif
-  InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
-
-  /* size of guard page */
-  InitialTeb.StackCommit += PAGE_SIZE;
-
-  /* Reserve stack */
-  InitialTeb.StackAllocate = NULL;
-  Status = NtAllocateVirtualMemory(ProcessHandle,
-                                  &InitialTeb.StackAllocate,
-                                  0,
-                                  &InitialTeb.StackReserve,
-                                  MEM_RESERVE,
-                                  PAGE_READWRITE);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("Error reserving stack space!\n");
-      SetLastErrorByStatus(Status);
-      return(NULL);
-    }
-
-  DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
-        InitialTeb.StackAllocate, InitialTeb.StackReserve);
-
-  InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
-  InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
-
-  DPRINT("StackBase: %p StackCommit: %p\n",
-        InitialTeb.StackBase, InitialTeb.StackCommit);
-
-  /* Commit stack page(s) */
-  Status = NtAllocateVirtualMemory(ProcessHandle,
-                                  &InitialTeb.StackLimit,
-                                  0,
-                                  &InitialTeb.StackCommit,
-                                  MEM_COMMIT,
-                                  PAGE_READWRITE);
-  if (!NT_SUCCESS(Status))
-    {
-      /* release the stack space */
-      NtFreeVirtualMemory(ProcessHandle,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("Error comitting stack page(s)!\n");
-      SetLastErrorByStatus(Status);
-      return(INVALID_HANDLE_VALUE);
-    }
-
-  DPRINT("StackLimit: %p\n",
-        InitialTeb.StackLimit);
-
-  /* Protect guard page */
-  Status = NtProtectVirtualMemory(ProcessHandle,
-                                 InitialTeb.StackLimit,
-                                 PAGE_SIZE,
-                                 PAGE_GUARD | PAGE_READWRITE,
-                                 &OldPageProtection);
-  if (!NT_SUCCESS(Status))
-    {
-      /* release the stack space */
-      NtFreeVirtualMemory(ProcessHandle,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-
-      DPRINT("Error comitting guard page!\n");
-      SetLastErrorByStatus(Status);
-      return(INVALID_HANDLE_VALUE);
-    }
-
-  memset(&ThreadContext,0,sizeof(CONTEXT));
-  ThreadContext.Eip = (ULONG)BaseProcessStart;
-  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)InitialTeb.StackBase - 6*4;
-  ThreadContext.EFlags = (1<<1) + (1<<9);
-
-  DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
-
-  /*
-   * Write in the initial stack.
-   */
-  InitialStack[0] = 0;
-  InitialStack[1] = (DWORD)lpStartAddress;
-  InitialStack[2] = PEB_BASE;
-
-  Status = ZwWriteVirtualMemory(ProcessHandle,
-                               (PVOID)ThreadContext.Esp,
-                               InitialStack,
-                               sizeof(InitialStack),
-                               &ResultLength);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT1("Failed to write initial stack.\n");
-      return(INVALID_HANDLE_VALUE);
-    }
-
-  Status = NtCreateThread(&ThreadHandle,
-                         THREAD_ALL_ACCESS,
-                         &ObjectAttributes,
-                         ProcessHandle,
-                         &ClientId,
-                         &ThreadContext,
-                         &InitialTeb,
-                         CreateSuspended);
-  if (!NT_SUCCESS(Status))
-    {
-      NtFreeVirtualMemory(ProcessHandle,
-                         InitialTeb.StackAllocate,
-                         &InitialTeb.StackReserve,
-                         MEM_RELEASE);
-      SetLastErrorByStatus(Status);
-      return(INVALID_HANDLE_VALUE);
-    }
-
-  if (lpThreadId != NULL)
-    {
-      memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
-    }
-
-  return(ThreadHandle);
+ OBJECT_ATTRIBUTES oaThreadAttribs;
+ CLIENT_ID cidClientId;
+ PVOID pTrueStartAddress;
+ NTSTATUS nErrCode;
+ HANDLE hThread;
+
+ /* convert the thread attributes */
+ RtlRosR32AttribsToNativeAttribs(&oaThreadAttribs, lpThreadAttributes);
+
+ /* native image */
+ if(Sii->Subsystem != IMAGE_SUBSYSTEM_NATIVE)
+  pTrueStartAddress = (PVOID)BaseProcessStart;
+ /* Win32 image */
+ else
+  pTrueStartAddress = (PVOID)RtlBaseProcessStartRoutine;
+
+ 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",
+  ProcessHandle,
+  &oaThreadAttribs,
+  dwCreationFlags & CREATE_SUSPENDED,
+  0,
+  Sii->StackReserve,
+  Sii->StackCommit,
+  pTrueStartAddress,
+  &hThread,
+  &cidClientId,
+  2,
+  lpStartAddress,
+  PEB_BASE
+ );
+
+ /* create the first thread */
+ nErrCode = RtlRosCreateUserThreadVa
+ (
+  ProcessHandle,
+  &oaThreadAttribs,
+  dwCreationFlags & CREATE_SUSPENDED,
+  0,
+  &(Sii->StackReserve),
+  &(Sii->StackCommit),
+  pTrueStartAddress,
+  &hThread,
+  &cidClientId,
+  2,
+  (ULONG_PTR)lpStartAddress,
+  (ULONG_PTR)PEB_BASE
+ );
+
+ /* failure */
+ if(!NT_SUCCESS(nErrCode))
+ {
+  SetLastErrorByStatus(nErrCode);
+  return NULL;
+ }
+ DPRINT
+ (
+  "StackReserve          %p\n"
+  "StackCommit           %p\n"
+  "ThreadHandle          %p\n"
+  "ClientId.UniqueThread %p\n",
+  Sii->StackReserve,
+  Sii->StackCommit,
+  hThread,
+  cidClientId.UniqueThread
+ );
+
+ /* success */
+ if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
+ return hThread;
 }
 
-HANDLE 
-KlMapFile(LPCWSTR lpApplicationName)
+HANDLE KlMapFile(LPCWSTR lpApplicationName)
 {
    HANDLE hFile;
    IO_STATUS_BLOCK IoStatusBlock;
@@ -455,20 +534,22 @@ KlMapFile(LPCWSTR lpApplicationName)
    return(hSection);
 }
 
-static NTSTATUS 
-KlInitPeb (HANDLE ProcessHandle,
-          PRTL_USER_PROCESS_PARAMETERS Ppb,
-          PVOID* ImageBaseAddress)
+static NTSTATUS KlInitPeb
+(
+ HANDLE ProcessHandle,
+ PRTL_USER_PROCESS_PARAMETERS Ppb,
+ PVOID * ImageBaseAddress
+)
 {
  NTSTATUS Status;
  PVOID PpbBase;
  ULONG PpbSize;
  ULONG BytesWritten;
  ULONG Offset;
  PVOID ParentEnv = NULL;
  PVOID EnvPtr = NULL;
  PWCHAR ptr;
  ULONG EnvSize = 0, EnvSize1 = 0;
+ NTSTATUS Status;
+ PVOID PpbBase;
+ ULONG PpbSize;
+ ULONG BytesWritten;
+ ULONG Offset;
+ PVOID ParentEnv = NULL;
+ PVOID EnvPtr = NULL;
+ PWCHAR ptr;
+ ULONG EnvSize = 0, EnvSize1 = 0;
 
    /* create the Environment */
    if (Ppb->Environment != NULL)
@@ -573,16 +654,19 @@ KlInitPeb (HANDLE ProcessHandle,
 
 
 WINBOOL STDCALL 
-CreateProcessW(LPCWSTR lpApplicationName,
-              LPWSTR lpCommandLine,
-              LPSECURITY_ATTRIBUTES lpProcessAttributes,
-              LPSECURITY_ATTRIBUTES lpThreadAttributes,
-              WINBOOL bInheritHandles,
-              DWORD dwCreationFlags,
-              LPVOID lpEnvironment,
-              LPCWSTR lpCurrentDirectory,
-              LPSTARTUPINFOW lpStartupInfo,
-              LPPROCESS_INFORMATION lpProcessInformation)
+CreateProcessW
+(
+ LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ WINBOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation
+)
 {
    HANDLE hSection, hProcess, hThread;
    NTSTATUS Status;
@@ -641,7 +725,7 @@ CreateProcessW(LPCWSTR lpApplicationName,
    {
       if (lpCommandLine[0] == L'"')
       {
-         wcscpy(TempApplicationNameW, &lpCommandLine[0]);
+         wcscpy(TempApplicationNameW, lpCommandLine + 1);
          s = wcschr(TempApplicationNameW, L'"');
          if (s == NULL)
          {
@@ -672,7 +756,10 @@ CreateProcessW(LPCWSTR lpApplicationName,
       return FALSE;
    }
 
-   if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
+   DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
+          lpApplicationName, lpCommandLine);
+
+   if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName)/sizeof(WCHAR), ImagePathName, &s))
    {
      return FALSE;
    }
@@ -688,7 +775,7 @@ CreateProcessW(LPCWSTR lpApplicationName,
          wcscat(TempCommandLineNameW, lpApplicationName);
          lpCommandLine = TempCommandLineNameW;
          wcscpy(TempApplicationNameW, L"cmd.exe");
-          if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
+          if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName)/sizeof(WCHAR), ImagePathName, &s))
          {
             return FALSE;
          }
@@ -738,7 +825,6 @@ CreateProcessW(LPCWSTR lpApplicationName,
                            TempCurrentDirectoryW);
      }
 
-   
    /*
     * Create a section for the executable
     */
@@ -926,7 +1012,7 @@ CreateProcessW(LPCWSTR lpApplicationName,
    /*
     * Get some information about the process
     */
-   ZwQueryInformationProcess(hProcess,
+   NtQueryInformationProcess(hProcess,
                             ProcessBasicInformation,
                             &ProcessBasicInfo,
                             sizeof(ProcessBasicInfo),
@@ -934,13 +1020,19 @@ CreateProcessW(LPCWSTR lpApplicationName,
    DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
          ProcessBasicInfo.UniqueProcessId);
    lpProcessInformation->dwProcessId = ProcessBasicInfo.UniqueProcessId;
-   
+
    /*
     * Tell the csrss server we are creating a new process
     */
    CsrRequest.Type = CSRSS_CREATE_PROCESS;
    CsrRequest.Data.CreateProcessRequest.NewProcessId = 
      ProcessBasicInfo.UniqueProcessId;
+   if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
+   {
+      /* Do not create a console for GUI applications */
+      dwCreationFlags &= ~CREATE_NEW_CONSOLE;
+      dwCreationFlags |= DETACHED_PROCESS;
+   }
    CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
    Status = CsrClientCallServer(&CsrRequest, 
                                &CsrReply,
@@ -1007,7 +1099,21 @@ CreateProcessW(LPCWSTR lpApplicationName,
    }
    if (IsConsoleHandle(Ppb->hStdError))
    {
-      Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;
+      CsrRequest.Type = CSRSS_DUPLICATE_HANDLE;
+      CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId;
+      CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle;
+      Status = CsrClientCallServer(&CsrRequest, 
+                         &CsrReply,
+                         sizeof(CSRSS_API_REQUEST),
+                         sizeof(CSRSS_API_REPLY));
+      if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
+      {
+        Ppb->hStdError = INVALID_HANDLE_VALUE;
+      }
+      else
+      {
+         Ppb->hStdError = CsrReply.Data.DuplicateHandleReply.Handle;
+      }
    }
    else
    {
@@ -1066,12 +1172,12 @@ CreateProcessW(LPCWSTR lpApplicationName,
    /*
     * Create the thread for the kernel
     */
-   DPRINT("Creating thread for process\n");
+   DPRINT("Creating thread for process (EntryPoint = 0x%.08x)\n",
+    ImageBaseAddress + (ULONG)Sii.EntryPoint);
    hThread =  KlCreateFirstThread(hProcess,
                                  lpThreadAttributes,
-                                 Sii.StackReserve,
-                                 Sii.StackCommit,
-                                 ImageBaseAddress + (ULONG)Sii.EntryPoint,
+          &Sii,
+          ImageBaseAddress + (ULONG)Sii.EntryPoint,
                                  dwCreationFlags,
                                  &lpProcessInformation->dwThreadId);
    if (hThread == INVALID_HANDLE_VALUE)