[KERNEL32]
[reactos.git] / dll / win32 / kernel32 / client / proc.c
index 1a542b0..0c4f36b 100644 (file)
@@ -1,10 +1,9 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/proc/proc.c
  * PURPOSE:         Process functions
- * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
+ * PROGRAMMERS:     Ariadne (ariadne@xs4all.nl)
  * UPDATE HISTORY:
  *                  Created 01/11/98
  */
 
 #include <k32.h>
 
-#define NDEBUG
+// #define NDEBUG
 #include <debug.h>
 
-typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
-
 /* GLOBALS *******************************************************************/
 
-static UNICODE_STRING CommandLineStringW;
-static ANSI_STRING CommandLineStringA;
+WaitForInputIdleType UserWaitForInputIdleRoutine;
+UNICODE_STRING BaseUnicodeCommandLine;
+ANSI_STRING BaseAnsiCommandLine;
 UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
-
-static BOOL bCommandLineInitialized = FALSE;
-
-WaitForInputIdleType  lpfnGlobalRegisterWaitForInputIdle;
-
-LPSTARTUPINFOA lpLocalStartupInfo = NULL;
-
-VOID WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
-
+LPSTARTUPINFOA BaseAnsiStartupInfo = NULL;
 PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
-
-#define CMD_STRING L"cmd /c "
-
-extern __declspec(noreturn)
-VOID
-CALLBACK
-ConsoleControlDispatcher(DWORD CodeAndFlag);
-
 BOOLEAN g_AppCertInitialized;
 BOOLEAN g_HaveAppCerts;
 LIST_ENTRY BasepAppCertDllsList;
 RTL_CRITICAL_SECTION gcsAppCert;
 PBASEP_APPCERT_EMBEDDED_FUNC fEmbeddedCertFunc;
 NTSTATUS g_AppCertStatus;
-
 RTL_QUERY_REGISTRY_TABLE BasepAppCertTable[2] =
 {
     {
@@ -59,13 +39,17 @@ RTL_QUERY_REGISTRY_TABLE BasepAppCertTable[2] =
         0,
         NULL,
         0
-    },
-    {}
+    }
 };
 
 PSAFER_REPLACE_PROCESS_THREAD_TOKENS g_SaferReplaceProcessThreadTokens;
 HMODULE gSaferHandle = (HMODULE)-1;
 
+VOID WINAPI
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
+
+#define CMD_STRING L"cmd /c "
+
 /* FUNCTIONS ****************************************************************/
 
 VOID
@@ -474,8 +458,6 @@ VOID
 WINAPI
 BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress)
 {
-    UINT uExitCode = 0;
-
     DPRINT("BaseProcessStartup(..) - setting up exception frame.\n");
 
     _SEH2_TRY
@@ -487,53 +469,23 @@ BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress)
                                sizeof(PPROCESS_START_ROUTINE));
 
         /* Call the Start Routine */
-        uExitCode = (lpStartAddress)();
+        ExitThread(lpStartAddress());
     }
     _SEH2_EXCEPT(BaseExceptionFilter(_SEH2_GetExceptionInformation()))
     {
-        /* Get the SEH Error */
-        uExitCode = _SEH2_GetExceptionCode();
+        /* Get the Exit code from the SEH Handler */
+        if (!BaseRunningInServerProcess)
+        {
+            /* Kill the whole process, usually */
+            ExitProcess(_SEH2_GetExceptionCode());
+        }
+        else
+        {
+            /* If running inside CSRSS, kill just this thread */
+            ExitThread(_SEH2_GetExceptionCode());
+        }
     }
     _SEH2_END;
-
-    /* Exit the Process with our error */
-    ExitProcess(uExitCode);
-}
-
-/*
- * Tells CSR that a new process was created
- */
-NTSTATUS
-WINAPI
-BasepNotifyCsrOfCreation(ULONG dwCreationFlags,
-                         IN HANDLE ProcessId,
-                         IN BOOL InheritHandles)
-{
-    ULONG Request = CREATE_PROCESS;
-    CSR_API_MESSAGE CsrRequest;
-    NTSTATUS Status;
-
-    DPRINT("BasepNotifyCsrOfCreation: Process: %lx, Flags %lx\n",
-            ProcessId, dwCreationFlags);
-
-    /* Fill out the request */
-    CsrRequest.Data.CreateProcessRequest.NewProcessId = ProcessId;
-    CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
-    CsrRequest.Data.CreateProcessRequest.bInheritHandles = InheritHandles;
-
-    /* Call CSR */
-    Status = CsrClientCallServer(&CsrRequest,
-                                 NULL,
-                                 MAKE_CSR_API(Request, CSR_NATIVE),
-                                 sizeof(CSR_API_MESSAGE));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
-    {
-        DPRINT1("Failed to tell csrss about new process\n");
-        return CsrRequest.Status;
-    }
-
-    /* Return Success */
-    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -541,26 +493,26 @@ WINAPI
 BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
                        IN PCLIENT_ID ClientId)
 {
-    ULONG Request = CREATE_THREAD;
-    CSR_API_MESSAGE CsrRequest;
     NTSTATUS Status;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_CREATE_THREAD CreateThreadRequest = &ApiMessage.Data.CreateThreadRequest;
 
     DPRINT("BasepNotifyCsrOfThread: Thread: %lx, Handle %lx\n",
             ClientId->UniqueThread, ThreadHandle);
 
     /* Fill out the request */
-    CsrRequest.Data.CreateThreadRequest.ClientId = *ClientId;
-    CsrRequest.Data.CreateThreadRequest.ThreadHandle = ThreadHandle;
+    CreateThreadRequest->ClientId = *ClientId;
+    CreateThreadRequest->ThreadHandle = ThreadHandle;
 
     /* Call CSR */
-    Status = CsrClientCallServer(&CsrRequest,
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
                                  NULL,
-                                 MAKE_CSR_API(Request, CSR_NATIVE),
-                                 sizeof(CSR_API_MESSAGE));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+                                 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateThread),
+                                 sizeof(BASE_CREATE_THREAD));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(ApiMessage.Status))
     {
-        DPRINT1("Failed to tell csrss about new thread\n");
-        return CsrRequest.Status;
+        DPRINT1("Failed to tell csrss about new thread: %lx %lx\n", Status, ApiMessage.Status);
+        return ApiMessage.Status;
     }
 
     /* Return Success */
@@ -575,14 +527,18 @@ WINAPI
 BasepCreateFirstThread(HANDLE ProcessHandle,
                        LPSECURITY_ATTRIBUTES lpThreadAttributes,
                        PSECTION_IMAGE_INFORMATION SectionImageInfo,
-                       PCLIENT_ID ClientId)
+                       PCLIENT_ID ClientId,
+                       BOOLEAN InheritHandles,
+                       DWORD dwCreationFlags)
 {
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES LocalObjectAttributes;
     POBJECT_ATTRIBUTES ObjectAttributes;
     CONTEXT Context;
     INITIAL_TEB InitialTeb;
-    NTSTATUS Status;
     HANDLE hThread;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_CREATE_PROCESS CreateProcessRequest = &ApiMessage.Data.CreateProcessRequest;
 
     DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
 
@@ -618,10 +574,23 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
         return NULL;
     }
 
-    Status = BasepNotifyCsrOfThread(hThread, ClientId);
-    if (!NT_SUCCESS(Status))
+    /* Fill out the request to notify CSRSS */
+    CreateProcessRequest->ClientId = *ClientId;
+    CreateProcessRequest->ProcessHandle = ProcessHandle;
+    CreateProcessRequest->ThreadHandle = hThread;
+    CreateProcessRequest->CreationFlags = dwCreationFlags;
+    CreateProcessRequest->bInheritHandles = InheritHandles;
+
+    /* Call CSR */
+    DPRINT1("Calling CsrClientCallServer from BasepCreateFirstThread...\n");
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                 NULL,
+                                 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess),
+                                 sizeof(BASE_CREATE_PROCESS));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(ApiMessage.Status))
     {
-        ASSERT(FALSE);
+        DPRINT1("Failed to tell csrss about new process: %lx %lx\n", Status, ApiMessage.Status);
+        return NULL;
     }
 
     /* Success */
@@ -810,8 +779,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
     if ((Size) && (Size <= (MAX_PATH + 4)))
     {
         /* Get the DLL Path */
-        DllPathString = BaseComputeProcessDllPath((LPWSTR)ApplicationPathName,
-                                                  lpEnvironment);
+        DllPathString = BaseComputeProcessDllPath(FullPath, lpEnvironment);
         if (!DllPathString)
         {
             /* Fail */
@@ -821,12 +789,13 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
 
         /* Initialize Strings */
         RtlInitUnicodeString(&DllPath, DllPathString);
-        RtlInitUnicodeString(&ImageName, ApplicationPathName);
+        RtlInitUnicodeString(&ImageName, FullPath);
     }
     else
     {
-        /* Get the DLL Path */
-        DllPathString = BaseComputeProcessDllPath(FullPath, lpEnvironment);
+        /* Couldn't get the path name. Just take the original path */
+        DllPathString = BaseComputeProcessDllPath((LPWSTR)ApplicationPathName,
+                                                  lpEnvironment);
         if (!DllPathString)
         {
             /* Fail */
@@ -836,7 +805,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
 
         /* Initialize Strings */
         RtlInitUnicodeString(&DllPath, DllPathString);
-        RtlInitUnicodeString(&ImageName, FullPath);
+        RtlInitUnicodeString(&ImageName, ApplicationPathName);
     }
 
     /* Initialize Strings */
@@ -921,7 +890,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
         /* Allocate and Initialize new Environment Block */
         Size = EnviroSize;
         ProcessParameters->Environment = NULL;
-        Status = ZwAllocateVirtualMemory(ProcessHandle,
+        Status = NtAllocateVirtualMemory(ProcessHandle,
                                          (PVOID*)&ProcessParameters->Environment,
                                          0,
                                          &Size,
@@ -930,7 +899,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
         if (!NT_SUCCESS(Status)) goto FailPath;
 
         /* Write the Environment Block */
-        Status = ZwWriteVirtualMemory(ProcessHandle,
+        Status = NtWriteVirtualMemory(ProcessHandle,
                                       ProcessParameters->Environment,
                                       lpEnvironment,
                                       EnviroSize,
@@ -1129,68 +1098,33 @@ VOID
 WINAPI
 InitCommandLines(VOID)
 {
-    PRTL_USER_PROCESS_PARAMETERS Params;
-
-    /* get command line */
-    Params = NtCurrentPeb()->ProcessParameters;
-    RtlNormalizeProcessParams (Params);
-
-    /* initialize command line buffers */
-    CommandLineStringW.Length = Params->CommandLine.Length;
-    CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR);
-    CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(),
-                                                HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
-                                                CommandLineStringW.MaximumLength);
-    if (CommandLineStringW.Buffer == NULL)
-    {
-        return;
-    }
-
-    RtlInitAnsiString(&CommandLineStringA, NULL);
-
-    /* Copy command line */
-    RtlCopyUnicodeString(&CommandLineStringW,
-                         &(Params->CommandLine));
-    CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0;
-
-    /* convert unicode string to ansi (or oem) */
-    if (bIsFileApiAnsi)
-        RtlUnicodeStringToAnsiString(&CommandLineStringA,
-                                     &CommandLineStringW,
-                                     TRUE);
-    else
-        RtlUnicodeStringToOemString(&CommandLineStringA,
-                                    &CommandLineStringW,
-                                    TRUE);
+    NTSTATUS Status;
 
-    CommandLineStringA.Buffer[CommandLineStringA.Length] = 0;
+    /* Read the UNICODE_STRING from the PEB */
+    BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
 
-    bCommandLineInitialized = TRUE;
+    /* Convert to ANSI_STRING for the *A callers */
+    Status = RtlUnicodeStringToAnsiString(&BaseAnsiCommandLine,
+                                          &BaseUnicodeCommandLine,
+                                          TRUE);
+    if (!NT_SUCCESS(Status)) RtlInitEmptyAnsiString(&BaseAnsiCommandLine, 0, 0);
 }
 
+/* PUBLIC FUNCTIONS ***********************************************************/
+
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessAffinityMask(HANDLE hProcess,
-                       PDWORD_PTR lpProcessAffinityMask,
-                       PDWORD_PTR lpSystemAffinityMask)
+GetProcessAffinityMask(IN HANDLE hProcess,
+                       OUT PDWORD_PTR lpProcessAffinityMask,
+                       OUT PDWORD_PTR lpSystemAffinityMask)
 {
     PROCESS_BASIC_INFORMATION ProcessInfo;
-    SYSTEM_BASIC_INFORMATION SystemInfo;
     NTSTATUS Status;
 
-    Status = NtQuerySystemInformation(SystemBasicInformation,
-                                      &SystemInfo,
-                                      sizeof(SystemInfo),
-                                      NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
+    /* Query information on the process from the kernel */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessBasicInformation,
                                        (PVOID)&ProcessInfo,
@@ -1198,174 +1132,239 @@ GetProcessAffinityMask(HANDLE hProcess,
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* Fail */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Copy the affinity mask, and get the system one from our shared data */
     *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask;
-    *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask;
-
+    *lpSystemAffinityMask = (DWORD)BaseStaticServerData->SysInfo.ActiveProcessorsAffinityMask;
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetProcessAffinityMask(HANDLE hProcess,
-                       DWORD_PTR dwProcessAffinityMask)
+SetProcessAffinityMask(IN HANDLE hProcess,
+                       IN DWORD_PTR dwProcessAffinityMask)
 {
     NTSTATUS Status;
 
+    /* Directly set the affinity mask */
     Status = NtSetInformationProcess(hProcess,
                                      ProcessAffinityMask,
                                      (PVOID)&dwProcessAffinityMask,
                                      sizeof(DWORD));
     if (!NT_SUCCESS(Status))
     {
+        /* Handle failure */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Everything was ok */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessShutdownParameters(LPDWORD lpdwLevel,
-                             LPDWORD lpdwFlags)
+GetProcessShutdownParameters(OUT LPDWORD lpdwLevel,
+                             OUT LPDWORD lpdwFlags)
 {
-    CSR_API_MESSAGE CsrRequest;
-    ULONG Request;
     NTSTATUS Status;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_GET_PROCESS_SHUTDOWN_PARAMS GetShutdownParametersRequest = &ApiMessage.Data.GetShutdownParametersRequest;
 
-    Request = GET_SHUTDOWN_PARAMETERS;
-    Status = CsrClientCallServer(&CsrRequest,
+    /* Ask CSRSS for shutdown information */
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
                                  NULL,
-                                 MAKE_CSR_API(Request, CSR_NATIVE),
-                                 sizeof(CSR_API_MESSAGE));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+                                 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetProcessShutdownParam),
+                                 sizeof(BASE_GET_PROCESS_SHUTDOWN_PARAMS));
+    if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(ApiMessage.Status)))
     {
-        BaseSetLastNTError(Status);
+        /* Return the failure from CSRSS */
+        BaseSetLastNTError(ApiMessage.Status);
         return FALSE;
     }
 
-    *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level;
-    *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags;
-
+    /* Get the data out of the LCP reply */
+    *lpdwLevel = GetShutdownParametersRequest->Level;
+    *lpdwFlags = GetShutdownParametersRequest->Flags;
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetProcessShutdownParameters(DWORD dwLevel,
-                             DWORD dwFlags)
+SetProcessShutdownParameters(IN DWORD dwLevel,
+                             IN DWORD dwFlags)
 {
-    CSR_API_MESSAGE CsrRequest;
-    ULONG Request;
     NTSTATUS Status;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_SET_PROCESS_SHUTDOWN_PARAMS SetShutdownParametersRequest = &ApiMessage.Data.SetShutdownParametersRequest;
 
-    CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
-    CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
-
-    Request = SET_SHUTDOWN_PARAMETERS;
-    Status = CsrClientCallServer(&CsrRequest,
+    /* Write the data into the CSRSS request and send it */
+    SetShutdownParametersRequest->Level = dwLevel;
+    SetShutdownParametersRequest->Flags = dwFlags;
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
                                  NULL,
-                                 MAKE_CSR_API(Request, CSR_NATIVE),
-                                 sizeof(CSR_API_MESSAGE));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+                                 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetProcessShutdownParam),
+                                 sizeof(BASE_SET_PROCESS_SHUTDOWN_PARAMS));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(ApiMessage.Status))
     {
-        BaseSetLastNTError(Status);
+        /* Return the failure from CSRSS */
+        BaseSetLastNTError(ApiMessage.Status);
         return FALSE;
     }
 
+    /* All went well */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessWorkingSetSize(HANDLE hProcess,
-                         PSIZE_T lpMinimumWorkingSetSize,
-                         PSIZE_T lpMaximumWorkingSetSize)
+GetProcessWorkingSetSizeEx(IN HANDLE hProcess,
+                           OUT PSIZE_T lpMinimumWorkingSetSize,
+                           OUT PSIZE_T lpMaximumWorkingSetSize,
+                           OUT PDWORD Flags)
 {
-    QUOTA_LIMITS QuotaLimits;
+    QUOTA_LIMITS_EX QuotaLimits;
     NTSTATUS Status;
 
+    /* Query the kernel about this */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessQuotaLimits,
                                        &QuotaLimits,
-                                       sizeof(QUOTA_LIMITS),
+                                       sizeof(QUOTA_LIMITS_EX),
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* Return error */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Copy the quota information out */
     *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize;
     *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize;
-
+    *Flags = QuotaLimits.Flags;
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetProcessWorkingSetSize(HANDLE hProcess,
-                         SIZE_T dwMinimumWorkingSetSize,
-                         SIZE_T dwMaximumWorkingSetSize)
+GetProcessWorkingSetSize(IN HANDLE hProcess,
+                         OUT PSIZE_T lpMinimumWorkingSetSize,
+                         OUT PSIZE_T lpMaximumWorkingSetSize)
 {
-    QUOTA_LIMITS QuotaLimits;
-    NTSTATUS Status;
-
-    QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
-    QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+    DWORD Dummy;
+    return GetProcessWorkingSetSizeEx(hProcess,
+                                      lpMinimumWorkingSetSize,
+                                      lpMaximumWorkingSetSize,
+                                      &Dummy);
+}
 
-    Status = NtSetInformationProcess(hProcess,
-                                     ProcessQuotaLimits,
-                                     &QuotaLimits,
-                                     sizeof(QUOTA_LIMITS));
-    if (!NT_SUCCESS(Status))
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessWorkingSetSizeEx(IN HANDLE hProcess,
+                           IN SIZE_T dwMinimumWorkingSetSize,
+                           IN SIZE_T dwMaximumWorkingSetSize,
+                           IN DWORD Flags)
+{
+    QUOTA_LIMITS_EX QuotaLimits;
+    NTSTATUS Status, ReturnStatus;
+    BOOL Result;
+    PVOID State;
+    ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
+
+    /* Zero out the input structure */
+    RtlZeroMemory(&QuotaLimits, sizeof(QuotaLimits));
+
+    /* Check if the caller sent any limits */
+    if ((dwMinimumWorkingSetSize) && (dwMaximumWorkingSetSize))
+    {
+        /* Write the quota information */
+        QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
+        QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+        QuotaLimits.Flags = Flags;
+
+        /* Acquire the required privilege */
+        Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
+
+        /* Request the new quotas */
+        ReturnStatus = NtSetInformationProcess(hProcess,
+                                               ProcessQuotaLimits,
+                                               &QuotaLimits,
+                                               sizeof(QuotaLimits));
+        Result = NT_SUCCESS(ReturnStatus);
+        if (NT_SUCCESS(Status))
+        {
+            /* Release the privilege and set succes code */
+            ASSERT(State != NULL);
+            RtlReleasePrivilege(State);
+            State = NULL;
+        }
+    }
+    else
     {
-        BaseSetLastNTError(Status);
-        return FALSE;
+        /* No limits, fail the call */
+        ReturnStatus = STATUS_INVALID_PARAMETER;
+        Result = FALSE;
     }
 
-    return TRUE;
+    /* Return result code, set error code if this was a failure */
+    if (!Result) BaseSetLastNTError(ReturnStatus);
+    return Result;
 }
 
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessWorkingSetSize(IN HANDLE hProcess,
+                         IN SIZE_T dwMinimumWorkingSetSize,
+                         IN SIZE_T dwMaximumWorkingSetSize)
+{
+    /* Call the newer API */
+    return SetProcessWorkingSetSizeEx(hProcess,
+                                      dwMinimumWorkingSetSize,
+                                      dwMaximumWorkingSetSize,
+                                      0);
+}
 
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessTimes(HANDLE hProcess,
-                LPFILETIME lpCreationTime,
-                LPFILETIME lpExitTime,
-                LPFILETIME lpKernelTime,
-                LPFILETIME lpUserTime)
+GetProcessTimes(IN HANDLE hProcess,
+                IN LPFILETIME lpCreationTime,
+                IN LPFILETIME lpExitTime,
+                IN LPFILETIME lpKernelTime,
+                IN LPFILETIME lpUserTime)
 {
     KERNEL_USER_TIMES Kut;
     NTSTATUS Status;
 
+    /* Query the times */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessTimes,
                                        &Kut,
@@ -1373,26 +1372,23 @@ GetProcessTimes(HANDLE hProcess,
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* Handle failure */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Copy all the times and return success */
     lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart;
     lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart;
-
     lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart;
     lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart;
-
     lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart;
     lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart;
-
     lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart;
     lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart;
-
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
@@ -1403,7 +1399,6 @@ GetCurrentProcess(VOID)
     return (HANDLE)NtCurrentProcess();
 }
 
-
 /*
  * @implemented
  */
@@ -1414,7 +1409,6 @@ GetCurrentThread(VOID)
     return (HANDLE)NtCurrentThread();
 }
 
-
 /*
  * @implemented
  */
@@ -1422,21 +1416,21 @@ DWORD
 WINAPI
 GetCurrentProcessId(VOID)
 {
-    return HandleToUlong(GetTeb()->ClientId.UniqueProcess);
+    return HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess);
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetExitCodeProcess(HANDLE hProcess,
-                   LPDWORD lpExitCode)
+GetExitCodeProcess(IN HANDLE hProcess,
+                   IN LPDWORD lpExitCode)
 {
     PROCESS_BASIC_INFORMATION ProcessBasic;
     NTSTATUS Status;
 
+    /* Ask the kernel */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessBasicInformation,
                                        &ProcessBasic,
@@ -1444,26 +1438,30 @@ GetExitCodeProcess(HANDLE hProcess,
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* We failed, was this because this is a VDM process? */
+        if (BaseCheckForVDM(hProcess, lpExitCode) == TRUE) return TRUE;
+
+        /* Not a VDM process, fail the call */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Succes case, return the exit code */
     *lpExitCode = (DWORD)ProcessBasic.ExitStatus;
-
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 DWORD
 WINAPI
-GetProcessId(HANDLE Process)
+GetProcessId(IN HANDLE Process)
 {
     PROCESS_BASIC_INFORMATION ProcessBasic;
     NTSTATUS Status;
 
+    /* Query the kernel */
     Status = NtQueryInformationProcess(Process,
                                        ProcessBasicInformation,
                                        &ProcessBasic,
@@ -1471,105 +1469,65 @@ GetProcessId(HANDLE Process)
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* Handle failure */
         BaseSetLastNTError(Status);
         return 0;
     }
 
+    /* Return the PID */
     return (DWORD)ProcessBasic.UniqueProcessId;
 }
 
-
 /*
  * @implemented
  */
 HANDLE
 WINAPI
-OpenProcess(DWORD dwDesiredAccess,
-            BOOL bInheritHandle,
-            DWORD dwProcessId)
+OpenProcess(IN DWORD dwDesiredAccess,
+            IN BOOL bInheritHandle,
+            IN DWORD dwProcessId)
 {
-    NTSTATUS errCode;
+    NTSTATUS Status;
     HANDLE ProcessHandle;
     OBJECT_ATTRIBUTES ObjectAttributes;
     CLIENT_ID ClientId;
 
+    /* Setup the input client ID structure */
     ClientId.UniqueProcess = UlongToHandle(dwProcessId);
     ClientId.UniqueThread = 0;
 
+    /* This is needed just to define the inheritance flags */
     InitializeObjectAttributes(&ObjectAttributes,
                                NULL,
                                (bInheritHandle ? OBJ_INHERIT : 0),
                                NULL,
                                NULL);
 
-    errCode = NtOpenProcess(&ProcessHandle,
-                            dwDesiredAccess,
-                            &ObjectAttributes,
-                            &ClientId);
-    if (!NT_SUCCESS(errCode))
+    /* Now try to open the process */
+    Status = NtOpenProcess(&ProcessHandle,
+                           dwDesiredAccess,
+                           &ObjectAttributes,
+                           &ClientId);
+    if (!NT_SUCCESS(Status))
     {
-        BaseSetLastNTError(errCode);
+        /* Handle failure */
+        BaseSetLastNTError(Status);
         return NULL;
     }
 
+    /* Otherwise return a handle to the process */
     return ProcessHandle;
 }
 
-
-/*
- * @implemented
- */
-UINT
-WINAPI
-WinExec(LPCSTR lpCmdLine,
-        UINT uCmdShow)
-{
-    STARTUPINFOA StartupInfo;
-    PROCESS_INFORMATION  ProcessInformation;
-    DWORD dosErr;
-
-    RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
-    StartupInfo.cb = sizeof(STARTUPINFOA);
-    StartupInfo.wShowWindow = (WORD)uCmdShow;
-    StartupInfo.dwFlags = 0;
-
-    if (!CreateProcessA(NULL,
-                        (PVOID)lpCmdLine,
-                        NULL,
-                        NULL,
-                        FALSE,
-                        0,
-                        NULL,
-                        NULL,
-                        &StartupInfo,
-                        &ProcessInformation))
-    {
-        dosErr = GetLastError();
-        return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
-    }
-
-    if (NULL != lpfnGlobalRegisterWaitForInputIdle)
-    {
-        lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,
-                                           10000);
-    }
-
-    NtClose(ProcessInformation.hProcess);
-    NtClose(ProcessInformation.hThread);
-
-    return 33; /* Something bigger than 31 means success. */
-}
-
-
 /*
  * @implemented
  */
 VOID
 WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
+RegisterWaitForInputIdle(IN WaitForInputIdleType lpfnRegisterWaitForInputIdle)
 {
-    lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
-    return;
+    /* Write the global function pointer */
+    UserWaitForInputIdleRoutine = lpfnRegisterWaitForInputIdle;
 }
 
 /*
@@ -1577,19 +1535,16 @@ RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
  */
 VOID
 WINAPI
-GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
+GetStartupInfoW(IN LPSTARTUPINFOW lpStartupInfo)
 {
     PRTL_USER_PROCESS_PARAMETERS Params;
 
-    if (lpStartupInfo == NULL)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return;
-    }
-
+    /* Get the process parameters */
     Params = NtCurrentPeb()->ProcessParameters;
 
+    /* Copy the data out of there */
     lpStartupInfo->cb = sizeof(STARTUPINFOW);
+    lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
     lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
     lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
     lpStartupInfo->dwX = Params->StartingX;
@@ -1604,298 +1559,396 @@ GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
     lpStartupInfo->cbReserved2 = Params->RuntimeData.Length;
     lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
 
-    lpStartupInfo->hStdInput = Params->StandardInput;
-    lpStartupInfo->hStdOutput = Params->StandardOutput;
-    lpStartupInfo->hStdError = Params->StandardError;
+    /* Check if the standard handles are being used for other features */
+    if (lpStartupInfo->dwFlags & (STARTF_USESTDHANDLES |
+                                  STARTF_USEHOTKEY |
+                                  STARTF_SHELLPRIVATE))
+    {
+        /* These are, so copy the standard handles too */
+        lpStartupInfo->hStdInput = Params->StandardInput;
+        lpStartupInfo->hStdOutput = Params->StandardOutput;
+        lpStartupInfo->hStdError = Params->StandardError;
+    }
 }
 
-
 /*
  * @implemented
  */
 VOID
 WINAPI
-GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
+GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo)
 {
     PRTL_USER_PROCESS_PARAMETERS Params;
-    ANSI_STRING AnsiString;
-
-    if (lpStartupInfo == NULL)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return;
-    }
-
-    Params = NtCurrentPeb ()->ProcessParameters;
+    ANSI_STRING TitleString, ShellString, DesktopString;
+    LPSTARTUPINFOA StartupInfo;
+    NTSTATUS Status;
 
-    RtlAcquirePebLock ();
+    /* Get the cached information as well as the PEB parameters */
+    StartupInfo = BaseAnsiStartupInfo;
+    Params = NtCurrentPeb()->ProcessParameters;
 
-    /* FIXME - not thread-safe */
-    if (lpLocalStartupInfo == NULL)
+    /* Check if this is the first time we have to get the cached version */
+    while (!StartupInfo)
     {
-        /* create new local startup info (ansi) */
-        lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
-                                             0,
-                                             sizeof(STARTUPINFOA));
-        if (lpLocalStartupInfo == NULL)
+        /* Create new ANSI startup info */
+        StartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+                                      0,
+                                      sizeof(*StartupInfo));
+        if (StartupInfo)
         {
-            RtlReleasePebLock();
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            return;
+            /* Zero out string pointers in case we fail to create them */
+            StartupInfo->lpReserved = 0;
+            StartupInfo->lpDesktop = 0;
+            StartupInfo->lpTitle = 0;
+
+            /* Set the size */
+            StartupInfo->cb = sizeof(*StartupInfo);
+
+            /* Copy what's already stored in the PEB */
+            StartupInfo->dwX = Params->StartingX;
+            StartupInfo->dwY = Params->StartingY;
+            StartupInfo->dwXSize = Params->CountX;
+            StartupInfo->dwYSize = Params->CountY;
+            StartupInfo->dwXCountChars = Params->CountCharsX;
+            StartupInfo->dwYCountChars = Params->CountCharsY;
+            StartupInfo->dwFillAttribute = Params->FillAttribute;
+            StartupInfo->dwFlags = Params->WindowFlags;
+            StartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
+            StartupInfo->cbReserved2 = Params->RuntimeData.Length;
+            StartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
+            StartupInfo->hStdInput = Params->StandardInput;
+            StartupInfo->hStdOutput = Params->StandardOutput;
+            StartupInfo->hStdError = Params->StandardError;
+
+            /* Copy shell info string */
+            Status = RtlUnicodeStringToAnsiString(&ShellString,
+                                                  &Params->ShellInfo,
+                                                  TRUE);
+            if (NT_SUCCESS(Status))
+            {
+                /* Save it */
+                StartupInfo->lpReserved = ShellString.Buffer;
+
+                /* Copy desktop info string */
+                Status = RtlUnicodeStringToAnsiString(&DesktopString,
+                                                      &Params->DesktopInfo,
+                                                      TRUE);
+                if (NT_SUCCESS(Status))
+                {
+                    /* Save it */
+                    StartupInfo->lpDesktop = DesktopString.Buffer;
+
+                    /* Copy window title string */
+                    Status = RtlUnicodeStringToAnsiString(&TitleString,
+                                                          &Params->WindowTitle,
+                                                          TRUE);
+                    if (NT_SUCCESS(Status))
+                    {
+                        /* Save it */
+                        StartupInfo->lpTitle = TitleString.Buffer;
+
+                        /* We finished with the ANSI version, try to cache it */
+                        if (!InterlockedCompareExchangePointer(&BaseAnsiStartupInfo,
+                                                               StartupInfo,
+                                                               NULL))
+                        {
+                            /* We were the first thread through, use the data */
+                            break;
+                        }
+
+                        /* Someone beat us to it, use their data instead */
+                        StartupInfo = BaseAnsiStartupInfo;
+                        Status = STATUS_SUCCESS;
+
+                        /* We're going to free our own stuff, but not raise */
+                        RtlFreeAnsiString(&TitleString);
+                    }
+                    RtlFreeAnsiString(&DesktopString);
+                }
+                RtlFreeAnsiString(&ShellString);
+            }
+            RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo);
+        }
+        else
+        {
+            /* No memory, fail */
+            Status = STATUS_NO_MEMORY;
         }
 
-        lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
-
-        /* copy window title string */
-        RtlUnicodeStringToAnsiString(&AnsiString,
-                                     &Params->WindowTitle,
-                                     TRUE);
-        lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
-
-        /* copy desktop info string */
-        RtlUnicodeStringToAnsiString(&AnsiString,
-                                     &Params->DesktopInfo,
-                                     TRUE);
-        lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
-
-        /* copy shell info string */
-        RtlUnicodeStringToAnsiString(&AnsiString,
-                                     &Params->ShellInfo,
-                                     TRUE);
-        lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
-
-        lpLocalStartupInfo->dwX = Params->StartingX;
-        lpLocalStartupInfo->dwY = Params->StartingY;
-        lpLocalStartupInfo->dwXSize = Params->CountX;
-        lpLocalStartupInfo->dwYSize = Params->CountY;
-        lpLocalStartupInfo->dwXCountChars = Params->CountCharsX;
-        lpLocalStartupInfo->dwYCountChars = Params->CountCharsY;
-        lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute;
-        lpLocalStartupInfo->dwFlags = Params->WindowFlags;
-        lpLocalStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
-        lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length;
-        lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
-
-        lpLocalStartupInfo->hStdInput = Params->StandardInput;
-        lpLocalStartupInfo->hStdOutput = Params->StandardOutput;
-        lpLocalStartupInfo->hStdError = Params->StandardError;
-    }
-
-    RtlReleasePebLock();
-
-    /* copy local startup info data to external startup info */
-    memcpy(lpStartupInfo,
-           lpLocalStartupInfo,
-           sizeof(STARTUPINFOA));
+        /* Raise an error unless we got here due to the race condition */
+        if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
+    }
+
+    /* Now copy from the cached ANSI version */
+    lpStartupInfo->cb = StartupInfo->cb;
+    lpStartupInfo->lpReserved = StartupInfo->lpReserved;
+    lpStartupInfo->lpDesktop = StartupInfo->lpDesktop;
+    lpStartupInfo->lpTitle = StartupInfo->lpTitle;
+    lpStartupInfo->dwX = StartupInfo->dwX;
+    lpStartupInfo->dwY = StartupInfo->dwY;
+    lpStartupInfo->dwXSize = StartupInfo->dwXSize;
+    lpStartupInfo->dwYSize = StartupInfo->dwYSize;
+    lpStartupInfo->dwXCountChars = StartupInfo->dwXCountChars;
+    lpStartupInfo->dwYCountChars = StartupInfo->dwYCountChars;
+    lpStartupInfo->dwFillAttribute = StartupInfo->dwFillAttribute;
+    lpStartupInfo->dwFlags = StartupInfo->dwFlags;
+    lpStartupInfo->wShowWindow = StartupInfo->wShowWindow;
+    lpStartupInfo->cbReserved2 = StartupInfo->cbReserved2;
+    lpStartupInfo->lpReserved2 = StartupInfo->lpReserved2;
+
+    /* Check if the shell is hijacking the handles for other features */
+    if (lpStartupInfo->dwFlags &
+        (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))
+    {
+        /* It isn't, so we can return the raw values */
+        lpStartupInfo->hStdInput = StartupInfo->hStdInput;
+        lpStartupInfo->hStdOutput = StartupInfo->hStdOutput;
+        lpStartupInfo->hStdError = StartupInfo->hStdError;
+    }
+    else
+    {
+        /* It is, so make sure nobody uses these as console handles */
+        lpStartupInfo->hStdInput = INVALID_HANDLE_VALUE;
+        lpStartupInfo->hStdOutput = INVALID_HANDLE_VALUE;
+        lpStartupInfo->hStdError = INVALID_HANDLE_VALUE;
+    }
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-FlushInstructionCache(HANDLE hProcess,
-                      LPCVOID lpBaseAddress,
-                      SIZE_T dwSize)
+FlushInstructionCache(IN HANDLE hProcess,
+                      IN LPCVOID lpBaseAddress,
+                      IN SIZE_T dwSize)
 {
     NTSTATUS Status;
 
-    Status = NtFlushInstructionCache(hProcess,
-                                     (PVOID)lpBaseAddress,
-                                     dwSize);
+    /* Call the native function */
+    Status = NtFlushInstructionCache(hProcess, (PVOID)lpBaseAddress, dwSize);
     if (!NT_SUCCESS(Status))
     {
+        /* Handle failure case */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* All good */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 VOID
 WINAPI
-ExitProcess(UINT uExitCode)
+ExitProcess(IN UINT uExitCode)
 {
-    CSR_API_MESSAGE CsrRequest;
-    ULONG Request;
-    NTSTATUS Status;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_EXIT_PROCESS ExitProcessRequest = &ApiMessage.Data.ExitProcessRequest;
 
-    /* kill sibling threads ... we want to be alone at this point */
-    NtTerminateProcess(NULL, 0);
+    ASSERT(!BaseRunningInServerProcess);
 
-    /* unload all dll's */
-    LdrShutdownProcess();
+    _SEH2_TRY
+    {
+        /* Acquire the PEB lock */
+        RtlAcquirePebLock();
 
-    /* notify csrss of process termination */
-    Request = TERMINATE_PROCESS;
-    Status = CsrClientCallServer(&CsrRequest,
-                                 NULL,
-                                 MAKE_CSR_API(Request, CSR_NATIVE),
-                                 sizeof(CSR_API_MESSAGE));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+        /* Kill all the threads */
+        NtTerminateProcess(NULL, 0);
+
+        /* Unload all DLLs */
+        LdrShutdownProcess();
+
+        /* Notify Base Server of process termination */
+        ExitProcessRequest->uExitCode = uExitCode;
+        CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                            NULL,
+                            CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepExitProcess),
+                            sizeof(BASE_EXIT_PROCESS));
+
+        /* Now do it again */
+        NtTerminateProcess(NtCurrentProcess(), uExitCode);
+    }
+    _SEH2_FINALLY
     {
-        DPRINT("Failed to tell csrss about terminating process\n");
+        /* Release the PEB lock */
+        RtlReleasePebLock();
     }
-
-    NtTerminateProcess(NtCurrentProcess (),
-                       uExitCode);
+    _SEH2_END;
 
     /* should never get here */
     ASSERT(0);
     while(1);
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-TerminateProcess(HANDLE hProcess,
-                 UINT uExitCode)
+TerminateProcess(IN HANDLE hProcess,
+                 IN UINT uExitCode)
 {
     NTSTATUS Status;
 
-    if (hProcess == NULL)
+    /* Check if no handle was passed in */
+    if (!hProcess)
     {
-      return FALSE;
+        /* Set error code */
+        SetLastError(ERROR_INVALID_HANDLE);
     }
-
-    Status = NtTerminateProcess(hProcess, uExitCode);
-    if (NT_SUCCESS(Status))
+    else
     {
-        return TRUE;
+        /* Otherwise, try to terminate the process */
+        Status = NtTerminateProcess(hProcess, uExitCode);
+        if (NT_SUCCESS(Status)) return TRUE;
+
+        /* It failed, convert error code */
+        BaseSetLastNTError(Status);
     }
 
-    BaseSetLastNTError(Status);
+    /* This is the failure path */
     return FALSE;
 }
 
-
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 WINAPI
 FatalAppExitA(UINT uAction,
               LPCSTR lpMessageText)
 {
-    UNICODE_STRING MessageTextU;
+    PUNICODE_STRING MessageTextU;
     ANSI_STRING MessageText;
+    NTSTATUS Status;
 
+    /* Initialize the string using the static TEB pointer */
+    MessageTextU = &NtCurrentTeb()->StaticUnicodeString;
     RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText);
 
-    RtlAnsiStringToUnicodeString(&MessageTextU,
-                                 &MessageText,
-                                 TRUE);
+    /* Convert to unicode and just exit normally if this failed */
+    Status = RtlAnsiStringToUnicodeString(MessageTextU, &MessageText, FALSE);
+    if (!NT_SUCCESS(Status)) ExitProcess(0);
 
-    FatalAppExitW(uAction, MessageTextU.Buffer);
-
-    RtlFreeUnicodeString(&MessageTextU);
+    /* Call the Wide function */
+    FatalAppExitW(uAction, MessageTextU->Buffer);
 }
 
-
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 WINAPI
-FatalAppExitW(UINT uAction,
-              LPCWSTR lpMessageText)
+FatalAppExitW(IN UINT uAction,
+              IN LPCWSTR lpMessageText)
 {
-    static const WCHAR szUser32[] = L"user32.dll\0";
-
-    HMODULE hModule = GetModuleHandleW(szUser32);
-    MessageBoxW_Proc pMessageBoxW = NULL;
+    UNICODE_STRING UnicodeString;
+    ULONG Response;
+    NTSTATUS Status;
 
-    DPRINT1("AppExit\n");
+    /* Setup the stirng to print out */
+    RtlInitUnicodeString(&UnicodeString, lpMessageText);
 
-    if (hModule)
-        pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW");
+    /* Display the hard error no matter what */
+    Status = NtRaiseHardError(STATUS_FATAL_APP_EXIT | HARDERROR_OVERRIDE_ERRORMODE,
+                              1,
+                              1,
+                              (PULONG_PTR)&UnicodeString,
+                              OptionOkCancel,
+                              &Response);
 
-    if (pMessageBoxW)
-        pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK);
-    else
-        DPRINT1("%s\n", lpMessageText);
+    /* Give the user a chance to abort */
+    if ((NT_SUCCESS(Status)) && (Response == ResponseCancel)) return;
 
+    /* Otherwise kill the process */
     ExitProcess(0);
 }
 
-
 /*
  * @implemented
  */
 VOID
 WINAPI
-FatalExit(int ExitCode)
+FatalExit(IN int ExitCode)
 {
+#if DBG
+    /* On Checked builds, Windows gives you a nice little debugger UI */
+    CHAR ch[2];
+    DbgPrint("FatalExit...\n");
+    DbgPrint("\n");
+
+    while (TRUE)
+    {
+        DbgPrompt( "A (Abort), B (Break), I (Ignore)? ", ch, sizeof(ch));
+        switch (ch[0])
+        {
+            case 'B': case 'b':
+                 DbgBreakPoint();
+                 break;
+
+            case 'A': case 'a':
+                ExitProcess(ExitCode);
+
+            case 'I': case 'i':
+                return;
+        }
+    }
+#endif
+    /* On other builds, just kill the process */
     ExitProcess(ExitCode);
 }
 
-
 /*
  * @implemented
  */
 DWORD
 WINAPI
-GetPriorityClass(HANDLE hProcess)
+GetPriorityClass(IN HANDLE hProcess)
 {
-  NTSTATUS Status;
-  PROCESS_PRIORITY_CLASS PriorityClass;
+    NTSTATUS Status;
+    PROCESS_PRIORITY_CLASS PriorityClass;
 
-  Status = NtQueryInformationProcess(hProcess,
-                                     ProcessPriorityClass,
-                                     &PriorityClass,
-                                     sizeof(PROCESS_PRIORITY_CLASS),
-                                     NULL);
-  if(NT_SUCCESS(Status))
-  {
-    switch(PriorityClass.PriorityClass)
+    /* Query the kernel */
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessPriorityClass,
+                                       &PriorityClass,
+                                       sizeof(PROCESS_PRIORITY_CLASS),
+                                       NULL);
+    if (NT_SUCCESS(Status))
     {
-      case PROCESS_PRIORITY_CLASS_IDLE:
-        return IDLE_PRIORITY_CLASS;
-
-      case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
-        return BELOW_NORMAL_PRIORITY_CLASS;
-
-      case PROCESS_PRIORITY_CLASS_NORMAL:
-        return NORMAL_PRIORITY_CLASS;
-
-      case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
-        return ABOVE_NORMAL_PRIORITY_CLASS;
-
-      case PROCESS_PRIORITY_CLASS_HIGH:
-        return HIGH_PRIORITY_CLASS;
-
-      case PROCESS_PRIORITY_CLASS_REALTIME:
-        return REALTIME_PRIORITY_CLASS;
-
-      default:
-        return NORMAL_PRIORITY_CLASS;
+        /* Handle the conversion from NT to Win32 classes */
+        switch (PriorityClass.PriorityClass)
+        {
+            case PROCESS_PRIORITY_CLASS_IDLE: return IDLE_PRIORITY_CLASS;
+            case PROCESS_PRIORITY_CLASS_BELOW_NORMAL: return BELOW_NORMAL_PRIORITY_CLASS;
+            case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: return ABOVE_NORMAL_PRIORITY_CLASS;
+            case PROCESS_PRIORITY_CLASS_HIGH: return HIGH_PRIORITY_CLASS;
+            case PROCESS_PRIORITY_CLASS_REALTIME: return REALTIME_PRIORITY_CLASS;
+            case PROCESS_PRIORITY_CLASS_NORMAL: default: return NORMAL_PRIORITY_CLASS;
+        }
     }
-  }
 
-  BaseSetLastNTError(Status);
-  return FALSE;
+    /* Failure path */
+    BaseSetLastNTError(Status);
+    return FALSE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetPriorityClass(HANDLE hProcess,
-                 DWORD dwPriorityClass)
+SetPriorityClass(IN HANDLE hProcess,
+                 IN DWORD dwPriorityClass)
 {
     NTSTATUS Status;
+    PVOID State = NULL;
     PROCESS_PRIORITY_CLASS PriorityClass;
 
+    /* Handle conversion from Win32 to NT priority classes */
     switch (dwPriorityClass)
     {
         case IDLE_PRIORITY_CLASS:
@@ -1919,68 +1972,85 @@ SetPriorityClass(HANDLE hProcess,
             break;
 
         case REALTIME_PRIORITY_CLASS:
-            PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
+            /* Try to acquire the privilege. If it fails, just use HIGH */
+            State = BasepIsRealtimeAllowed(TRUE);
+            PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
+            PriorityClass.PriorityClass += (State != NULL);
             break;
 
         default:
+            /* Unrecognized priority classes don't make it to the kernel */
             SetLastError(ERROR_INVALID_PARAMETER);
             return FALSE;
     }
 
+    /* Send the request to the kernel, and don't touch the foreground flag */
     PriorityClass.Foreground = FALSE;
-
     Status = NtSetInformationProcess(hProcess,
                                      ProcessPriorityClass,
                                      &PriorityClass,
                                      sizeof(PROCESS_PRIORITY_CLASS));
+
+    /* Release the privilege if we had it */
+    if (State) RtlReleasePrivilege(State);
     if (!NT_SUCCESS(Status))
     {
+        /* Handle error path */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* All done */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 DWORD
 WINAPI
-GetProcessVersion(DWORD ProcessId)
+GetProcessVersion(IN DWORD ProcessId)
 {
     DWORD Version = 0;
-    PIMAGE_NT_HEADERS NtHeader = NULL;
-    IMAGE_NT_HEADERS NtHeaders;
-    IMAGE_DOS_HEADER DosHeader;
+    PIMAGE_NT_HEADERS NtHeader;
+    PIMAGE_DOS_HEADER DosHeader;
+    PPEB Peb;
     PROCESS_BASIC_INFORMATION ProcessBasicInfo;
-    PVOID BaseAddress = NULL;
+    PVOID BaseAddress;
+    ULONG e_lfanew;
     HANDLE ProcessHandle = NULL;
     NTSTATUS Status;
-    SIZE_T Count;
-    PEB Peb;
+    USHORT VersionData[2];
+    BOOLEAN Result;
 
+    /* We'll be accessing stuff that can fault, so protect everything with SEH */
     _SEH2_TRY
     {
-        if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
+        /* It this an in-process or out-of-process request? */
+        if (!(ProcessId) || (GetCurrentProcessId() == ProcessId))
         {
-            /* Caller's */
-            BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
-            NtHeader = RtlImageNtHeader(BaseAddress);
+            /* It's in-process, so just read our own header */
+            NtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+            if (!NtHeader)
+            {
+                /* Unable to read the NT header, something is wrong here... */
+                Status = STATUS_INVALID_IMAGE_FORMAT;
+                goto Error;
+            }
 
-            Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
-                      (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
+            /* Get the version straight out of the NT header */
+            Version = MAKELONG(NtHeader->OptionalHeader.MinorSubsystemVersion,
+                               NtHeader->OptionalHeader.MajorSubsystemVersion);
         }
         else
         {
-            /* Other process */
+            /* Out-of-process, so open it */
             ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
                                         FALSE,
                                         ProcessId);
-
             if (!ProcessHandle) return 0;
 
+            /* Try to find out where its PEB lives */
             Status = NtQueryInformationProcess(ProcessHandle,
                                                ProcessBasicInformation,
                                                &ProcessBasicInfo,
@@ -1988,65 +2058,64 @@ GetProcessVersion(DWORD ProcessId)
                                                NULL);
 
             if (!NT_SUCCESS(Status)) goto Error;
+            Peb = ProcessBasicInfo.PebBaseAddress;
 
-            Status = NtReadVirtualMemory(ProcessHandle,
-                                         ProcessBasicInfo.PebBaseAddress,
-                                         &Peb,
-                                         sizeof(Peb),
-                                         &Count);
-
-            if (!NT_SUCCESS(Status) || Count != sizeof(Peb)) goto Error;
-
-            memset(&DosHeader, 0, sizeof(DosHeader));
-            Status = NtReadVirtualMemory(ProcessHandle,
-                                         Peb.ImageBaseAddress,
-                                         &DosHeader,
-                                         sizeof(DosHeader),
-                                         &Count);
-
-            if (!NT_SUCCESS(Status) || Count != sizeof(DosHeader)) goto Error;
-            if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) goto Error;
-
-            memset(&NtHeaders, 0, sizeof(NtHeaders));
-            Status = NtReadVirtualMemory(ProcessHandle,
-                                         (char *)Peb.ImageBaseAddress + DosHeader.e_lfanew,
-                                         &NtHeaders,
-                                         sizeof(NtHeaders),
-                                         &Count);
-
-            if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders)) goto Error;
-            if (NtHeaders.Signature != IMAGE_NT_SIGNATURE) goto Error;
+            /* Now that we have the PEB, read the image base address out of it */
+            Result = ReadProcessMemory(ProcessHandle,
+                                       &Peb->ImageBaseAddress,
+                                       &BaseAddress,
+                                       sizeof(BaseAddress),
+                                       NULL);
+            if (!Result) goto Error;
+
+            /* Now read the e_lfanew (offset to NT header) from the base */
+            DosHeader = BaseAddress;
+            Result = ReadProcessMemory(ProcessHandle,
+                                       &DosHeader->e_lfanew,
+                                       &e_lfanew,
+                                       sizeof(e_lfanew),
+                                       NULL);
+            if (!Result) goto Error;
+
+            /* And finally, read the NT header itself by adding the offset */
+            NtHeader = (PVOID)((ULONG_PTR)BaseAddress + e_lfanew);
+            Result = ReadProcessMemory(ProcessHandle,
+                                       &NtHeader->OptionalHeader.MajorSubsystemVersion,
+                                       &VersionData,
+                                       sizeof(VersionData),
+                                       NULL);
+            if (!Result) goto Error;
 
-            Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
-                               NtHeaders.OptionalHeader.MajorSubsystemVersion);
+            /* Get the version straight out of the NT header */
+            Version = MAKELONG(VersionData[0], VersionData[1]);
 
 Error:
-            if (!NT_SUCCESS(Status))
-            {
-                BaseSetLastNTError(Status);
-            }
+            /* If there was an error anywhere, set the last error */
+            if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status);
         }
     }
     _SEH2_FINALLY
     {
+        /* Close the process handle */
         if (ProcessHandle) CloseHandle(ProcessHandle);
     }
     _SEH2_END;
 
+    /* And return the version data */
     return Version;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessIoCounters(HANDLE hProcess,
-                     PIO_COUNTERS lpIoCounters)
+GetProcessIoCounters(IN HANDLE hProcess,
+                     OUT PIO_COUNTERS lpIoCounters)
 {
     NTSTATUS Status;
 
+    /* Query the kernel. Structures are identical, so let it do the copy too. */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessIoCounters,
                                        lpIoCounters,
@@ -2054,25 +2123,27 @@ GetProcessIoCounters(HANDLE hProcess,
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
+        /* Handle error path */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* All done */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessPriorityBoost(HANDLE hProcess,
-                        PBOOL pDisablePriorityBoost)
+GetProcessPriorityBoost(IN HANDLE hProcess,
+                        OUT PBOOL pDisablePriorityBoost)
 {
     NTSTATUS Status;
     ULONG PriorityBoost;
 
+    /* Query the kernel */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessPriorityBoost,
                                        &PriorityBoost,
@@ -2080,78 +2151,85 @@ GetProcessPriorityBoost(HANDLE hProcess,
                                        NULL);
     if (NT_SUCCESS(Status))
     {
-        *pDisablePriorityBoost = PriorityBoost;
+        /* Convert from ULONG to a BOOL */
+        *pDisablePriorityBoost = PriorityBoost ? TRUE : FALSE;
         return TRUE;
     }
 
+    /* Handle error path */
     BaseSetLastNTError(Status);
     return FALSE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetProcessPriorityBoost(HANDLE hProcess,
-                        BOOL bDisablePriorityBoost)
+SetProcessPriorityBoost(IN HANDLE hProcess,
+                        IN BOOL bDisablePriorityBoost)
 {
     NTSTATUS Status;
-    ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
+    ULONG PriorityBoost;
 
+    /* Enforce that this is a BOOL, and send it to the kernel as a ULONG */
+    PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE);
     Status = NtSetInformationProcess(hProcess,
                                      ProcessPriorityBoost,
                                      &PriorityBoost,
                                      sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
+        /* Handle error path */
         BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* All done */
     return TRUE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-GetProcessHandleCount(HANDLE hProcess,
-                      PDWORD pdwHandleCount)
+GetProcessHandleCount(IN HANDLE hProcess,
+                      OUT PDWORD pdwHandleCount)
 {
     ULONG phc;
     NTSTATUS Status;
 
+    /* Query the kernel */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessHandleCount,
                                        &phc,
                                        sizeof(ULONG),
                                        NULL);
-    if(NT_SUCCESS(Status))
+    if (NT_SUCCESS(Status))
     {
-      *pdwHandleCount = phc;
-      return TRUE;
+        /* Copy the count and return sucecss */
+        *pdwHandleCount = phc;
+        return TRUE;
     }
 
+    /* Handle error path */
     BaseSetLastNTError(Status);
     return FALSE;
 }
 
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-IsWow64Process(HANDLE hProcess,
-               PBOOL Wow64Process)
+IsWow64Process(IN HANDLE hProcess,
+               OUT PBOOL Wow64Process)
 {
     ULONG_PTR pbi;
     NTSTATUS Status;
 
+    /* Query the kernel */
     Status = NtQueryInformationProcess(hProcess,
                                        ProcessWow64Information,
                                        &pbi,
@@ -2159,12 +2237,13 @@ IsWow64Process(HANDLE hProcess,
                                        NULL);
     if (!NT_SUCCESS(Status))
     {
-        SetLastError(RtlNtStatusToDosError(Status));
+        /* Handle error path */
+        BaseSetLastNTError(Status);
         return FALSE;
     }
 
+    /* Enforce this is a BOOL, and return success */
     *Wow64Process = (pbi != 0);
-
     return TRUE;
 }
 
@@ -2175,11 +2254,9 @@ LPSTR
 WINAPI
 GetCommandLineA(VOID)
 {
-    DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer);
-    return CommandLineStringA.Buffer;
+    return BaseAnsiCommandLine.Buffer;
 }
 
-
 /*
  * @implemented
  */
@@ -2187,8 +2264,7 @@ LPWSTR
 WINAPI
 GetCommandLineW(VOID)
 {
-    DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer);
-    return CommandLineStringW.Buffer;
+    return BaseUnicodeCommandLine.Buffer;
 }
 
 /*
@@ -2209,11 +2285,14 @@ ReadProcessMemory(IN HANDLE hProcess,
                                  (PVOID)lpBaseAddress,
                                  lpBuffer,
                                  nSize,
-                                 lpNumberOfBytesRead);
+                                 &nSize);
+
+    /* In user-mode, this parameter is optional */
+    if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
     if (!NT_SUCCESS(Status))
     {
         /* We failed */
-        BaseSetLastNTError (Status);
+        BaseSetLastNTError(Status);
         return FALSE;
     }
 
@@ -2269,7 +2348,11 @@ WriteProcessMemory(IN HANDLE hProcess,
                                           lpBaseAddress,
                                           (LPVOID)lpBuffer,
                                           nSize,
-                                          lpNumberOfBytesWritten);
+                                          &nSize);
+
+            /* In Win32, the parameter is optional, so handle this case */
+            if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
+
             if (!NT_SUCCESS(Status))
             {
                 /* We failed */
@@ -2284,7 +2367,7 @@ WriteProcessMemory(IN HANDLE hProcess,
         else
         {
             /* Check if we were read only */
-            if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY))
+            if (OldValue & (PAGE_NOACCESS | PAGE_READONLY))
             {
                 /* Restore protection and fail */
                 NtProtectVirtualMemory(hProcess,
@@ -2293,7 +2376,9 @@ WriteProcessMemory(IN HANDLE hProcess,
                                        OldValue,
                                        &OldValue);
                 BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
-                return FALSE;
+
+                /* Note: This is what Windows returns and code depends on it */
+                return STATUS_ACCESS_VIOLATION;
             }
 
             /* Otherwise, do the write */
@@ -2301,7 +2386,10 @@ WriteProcessMemory(IN HANDLE hProcess,
                                           lpBaseAddress,
                                           (LPVOID)lpBuffer,
                                           nSize,
-                                          lpNumberOfBytesWritten);
+                                          &nSize);
+
+            /* In Win32, the parameter is optional, so handle this case */
+            if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
 
             /* And restore the protection */
             NtProtectVirtualMemory(hProcess,
@@ -2313,7 +2401,9 @@ WriteProcessMemory(IN HANDLE hProcess,
             {
                 /* We failed */
                 BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
-                return FALSE;
+
+                /* Note: This is what Windows returns and code depends on it */
+                return STATUS_ACCESS_VIOLATION;
             }
 
             /* Flush the ITLB */
@@ -2335,7 +2425,7 @@ WriteProcessMemory(IN HANDLE hProcess,
 BOOL
 WINAPI
 ProcessIdToSessionId(IN DWORD dwProcessId,
-                     OUT DWORD *pSessionId)
+                     OUT PDWORD pSessionId)
 {
     PROCESS_SESSION_INFORMATION SessionInformation;
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -2343,64 +2433,46 @@ ProcessIdToSessionId(IN DWORD dwProcessId,
     HANDLE ProcessHandle;
     NTSTATUS Status;
 
+    /* Do a quick check if the pointer is not writable */
     if (IsBadWritePtr(pSessionId, sizeof(DWORD)))
     {
+        /* Fail fast */
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
+    /* Open the process passed in by ID */
     ClientId.UniqueProcess = UlongToHandle(dwProcessId);
     ClientId.UniqueThread = 0;
-
     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
-
     Status = NtOpenProcess(&ProcessHandle,
                            PROCESS_QUERY_INFORMATION,
                            &ObjectAttributes,
                            &ClientId);
     if (NT_SUCCESS(Status))
     {
+        /* Query the session ID from the kernel */
         Status = NtQueryInformationProcess(ProcessHandle,
                                            ProcessSessionInformation,
                                            &SessionInformation,
                                            sizeof(SessionInformation),
                                            NULL);
-        NtClose(ProcessHandle);
 
+        /* Close the handle and check if we suceeded */
+        NtClose(ProcessHandle);
         if (NT_SUCCESS(Status))
         {
+            /* Return the session ID */
             *pSessionId = SessionInformation.SessionId;
             return TRUE;
         }
     }
 
+    /* Set error code and fail */
     BaseSetLastNTError(Status);
     return FALSE;
 }
 
-BOOL
-WINAPI
-SetProcessWorkingSetSizeEx(IN HANDLE hProcess,
-                           IN SIZE_T dwMinimumWorkingSetSize,
-                           IN SIZE_T dwMaximumWorkingSetSize,
-                           IN DWORD Flags)
-{
-    STUB;
-    return FALSE;
-}
-
-
-BOOL
-WINAPI
-GetProcessWorkingSetSizeEx(IN HANDLE hProcess,
-                           OUT PSIZE_T lpMinimumWorkingSetSize,
-                           OUT PSIZE_T lpMaximumWorkingSetSize,
-                           OUT PDWORD Flags)
-{
-    STUB;
-    return FALSE;
-}
-
 /*
  * @implemented
  */
@@ -2880,7 +2952,7 @@ GetAppName:
     /* FIXME: Allow CREATE_SEPARATE only for WOW Apps, once we have that. */
 
     /* Get some information about the executable */
-    Status = ZwQuerySection(hSection,
+    Status = NtQuerySection(hSection,
                             SectionImageInformation,
                             &SectionImageInfo,
                             sizeof(SectionImageInfo),
@@ -2909,7 +2981,11 @@ GetAppName:
         IMAGE_SUBSYSTEM_WINDOWS_CUI != SectionImageInfo.SubSystemType)
     {
         DPRINT1("Invalid subsystem %d\n", SectionImageInfo.SubSystemType);
-        SetLastError(ERROR_BAD_EXE_FORMAT);
+        /*
+         * Despite the name of the error code suggests, it corresponds to the
+         * well-known "The %1 application cannot be run in Win32 mode" message.
+         */
+        SetLastError(ERROR_CHILD_NOT_COMPLETE);
         goto Cleanup;
     }
 
@@ -2949,7 +3025,8 @@ GetAppName:
         /* Check if only this process will be debugged */
         if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
         {
-            /* FIXME: Set process flag */
+            /* Set process flag */
+            hDebug = (HANDLE)((ULONG_PTR)hDebug | 0x1);
         }
     }
 
@@ -3157,25 +3234,15 @@ GetAppName:
                                      &RemoteParameters->StandardError);
     }
 
-    /* Notify CSRSS */
-    Status = BasepNotifyCsrOfCreation(dwCreationFlags,
-                                      (HANDLE)ProcessBasicInfo.UniqueProcessId,
-                                      bInheritHandles);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("CSR Notification Failed\n");
-        BaseSetLastNTError(Status);
-        goto Cleanup;
-    }
-
     /* Create the first thread */
     DPRINT("Creating thread for process (EntryPoint = 0x%p)\n",
             SectionImageInfo.TransferAddress);
     hThread = BasepCreateFirstThread(hProcess,
                                      lpThreadAttributes,
                                      &SectionImageInfo,
-                                     &ClientId);
+                                     &ClientId,
+                                     bInheritHandles,
+                                     dwCreationFlags);
 
     if (hThread == NULL)
     {
@@ -3211,7 +3278,7 @@ Cleanup:
     if (hSection) NtClose(hSection);
     if (hThread)
     {
-        /* We don't know any more details then this */
+        /* We don't know any more details than this */
         NtTerminateProcess(hProcess, STATUS_UNSUCCESSFUL);
         NtClose(hThread);
     }
@@ -3420,4 +3487,48 @@ CreateProcessA(LPCSTR lpApplicationName,
                                   NULL);
 }
 
+/*
+ * @implemented
+ */
+UINT
+WINAPI
+WinExec(LPCSTR lpCmdLine,
+        UINT uCmdShow)
+{
+    STARTUPINFOA StartupInfo;
+    PROCESS_INFORMATION  ProcessInformation;
+    DWORD dosErr;
+
+    RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
+    StartupInfo.cb = sizeof(STARTUPINFOA);
+    StartupInfo.wShowWindow = (WORD)uCmdShow;
+    StartupInfo.dwFlags = 0;
+
+    if (!CreateProcessA(NULL,
+                        (PVOID)lpCmdLine,
+                        NULL,
+                        NULL,
+                        FALSE,
+                        0,
+                        NULL,
+                        NULL,
+                        &StartupInfo,
+                        &ProcessInformation))
+    {
+        dosErr = GetLastError();
+        return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
+    }
+
+    if (NULL != UserWaitForInputIdleRoutine)
+    {
+        UserWaitForInputIdleRoutine(ProcessInformation.hProcess,
+                                           10000);
+    }
+
+    NtClose(ProcessInformation.hProcess);
+    NtClose(ProcessInformation.hThread);
+
+    return 33; /* Something bigger than 31 means success. */
+}
+
 /* EOF */