Use ASSERT() instead of assert().
[reactos.git] / reactos / lib / kernel32 / process / proc.c
index 68e11b3..7cc029c 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id: proc.c,v 1.72 2004/11/05 12:26:55 ekohl Exp $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/proc/proc.c
 
 /* INCLUDES ****************************************************************/
 
-#define UNICODE
-#include <windows.h>
-#include <kernel32/proc.h>
-#include <kernel32/thread.h>
-#include <wstring.h>
-#include <string.h>
-#include <ddk/rtl.h>
-#include <ddk/li.h>
-#include <internal/i386/segment.h>
+#include <k32.h>
 
 #define NDEBUG
-#include <kernel32/kernel32.h>
+#include "../include/debug.h"
 
-/* GLOBALS *****************************************************************/
 
-static NT_PEB CurrentPeb;
-static PROCESSINFOW ProcessInfo;
+/* GLOBALS *******************************************************************/
 
 WaitForInputIdleType  lpfnGlobalRegisterWaitForInputIdle;
 
-VOID RegisterWaitForInputIdle(WaitForInputIdleType  lpfnRegisterWaitForInputIdle);
+LPSTARTUPINFOA lpLocalStartupInfo = NULL;
 
-/* FUNCTIONS ****************************************************************/
+VOID STDCALL
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
 
-WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId);
+/* FUNCTIONS ****************************************************************/
 
-VOID InitializePeb(PWSTR CommandLine)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessAffinityMask (HANDLE hProcess,
+                       LPDWORD lpProcessAffinityMask,
+                       LPDWORD lpSystemAffinityMask)
 {
-   DPRINT("InitializePeb(CommandLine %x)\n",CommandLine);
-//   DPRINT("ProcessInfo.CommandLine %x\n",ProcessInfo.CommandLine);
-//   wcscpy(ProcessInfo.CommandLine, CommandLine);
-   CurrentPeb.StartupInfo = &ProcessInfo;
+  PROCESS_BASIC_INFORMATION ProcessInfo;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess (hProcess,
+                                     ProcessBasicInformation,
+                                     (PVOID)&ProcessInfo,
+                                     sizeof(PROCESS_BASIC_INFORMATION),
+                                     NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask;
+
+  /* FIXME */
+  *lpSystemAffinityMask  = 0x00000001;
+
+  return TRUE;
 }
 
-NT_PEB *GetCurrentPeb(VOID)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessAffinityMask (HANDLE hProcess,
+                       DWORD dwProcessAffinityMask)
 {
-   return(&CurrentPeb);
+  NTSTATUS Status;
+
+  Status = NtSetInformationProcess (hProcess,
+                                   ProcessAffinityMask,
+                                   (PVOID)&dwProcessAffinityMask,
+                                   sizeof(DWORD));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
-HANDLE STDCALL GetCurrentProcess(VOID)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessShutdownParameters (LPDWORD lpdwLevel,
+                             LPDWORD lpdwFlags)
 {
-       return (HANDLE)NtCurrentProcess();
+  CSRSS_API_REQUEST CsrRequest;
+  CSRSS_API_REPLY CsrReply;
+  NTSTATUS Status;
+
+  CsrRequest.Type = CSRSS_GET_SHUTDOWN_PARAMETERS;
+  Status = CsrClientCallServer(&CsrRequest,
+                              &CsrReply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
+    {
+      SetLastErrorByStatus (Status);
+      return(FALSE);
+    }
+
+  *lpdwLevel = CsrReply.Data.GetShutdownParametersReply.Level;
+  *lpdwFlags = CsrReply.Data.GetShutdownParametersReply.Flags;
+
+  return(TRUE);
 }
 
-HANDLE STDCALL GetCurrentThread(VOID)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessShutdownParameters (DWORD dwLevel,
+                             DWORD dwFlags)
 {
-       return (HANDLE)NtCurrentThread();
+  CSRSS_API_REQUEST CsrRequest;
+  CSRSS_API_REPLY CsrReply;
+  NTSTATUS Status;
+
+  CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
+  CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
+
+  CsrRequest.Type = CSRSS_SET_SHUTDOWN_PARAMETERS;
+  Status = CsrClientCallServer(&CsrRequest,
+                              &CsrReply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
+    {
+      SetLastErrorByStatus (Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
-DWORD STDCALL GetCurrentProcessId(VOID)
-{      
-       return (DWORD)(GetTeb()->Cid).UniqueProcess;            
-}
 
-WINBOOL STDCALL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessWorkingSetSize (HANDLE hProcess,
+                         PSIZE_T lpMinimumWorkingSetSize,
+                         PSIZE_T lpMaximumWorkingSetSize)
 {
-   NTSTATUS errCode;
-   PROCESS_BASIC_INFORMATION ProcessBasic;
-   ULONG BytesWritten;
-   
-   errCode = NtQueryInformationProcess(hProcess,
-                                      ProcessBasicInformation,
-                                      &ProcessBasic,
-                                      sizeof(PROCESS_BASIC_INFORMATION),
-                                      &BytesWritten);
-   if (!NT_SUCCESS(errCode)) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-   memcpy( lpExitCode ,&ProcessBasic.ExitStatus,sizeof(DWORD));
-   return TRUE;        
+  QUOTA_LIMITS QuotaLimits;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessQuotaLimits,
+                                    &QuotaLimits,
+                                    sizeof(QUOTA_LIMITS),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize;
+  *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize;
+
+  return(TRUE);
 }
 
-WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId )
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessWorkingSetSize(HANDLE hProcess,
+                        SIZE_T dwMinimumWorkingSetSize,
+                        SIZE_T dwMaximumWorkingSetSize)
 {
-   NTSTATUS errCode;
-   PROCESS_BASIC_INFORMATION ProcessBasic;
-   ULONG BytesWritten;
-
-   errCode = NtQueryInformationProcess(hProcess,
-                                      ProcessBasicInformation,
-                                      &ProcessBasic,
-                                      sizeof(PROCESS_BASIC_INFORMATION),
-                                      &BytesWritten);
-   if (!NT_SUCCESS(errCode)) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-   memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD));
-   return TRUE;        
+  QUOTA_LIMITS QuotaLimits;
+  NTSTATUS Status;
+  
+  QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
+  QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+
+  Status = NtSetInformationProcess(hProcess,
+                                  ProcessQuotaLimits,
+                                  &QuotaLimits,
+                                  sizeof(QUOTA_LIMITS));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  return(TRUE);
 }
 
-PWSTR InternalAnsiToUnicode(PWSTR Out, LPCSTR In, ULONG MaxLength)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessTimes(HANDLE hProcess,
+               LPFILETIME lpCreationTime,
+               LPFILETIME lpExitTime,
+               LPFILETIME lpKernelTime,
+               LPFILETIME lpUserTime)
 {
-   ULONG i;
-   
-   if (In == NULL)
-     {
-       return(NULL);
-     }
-   else
-     {
-       i = 0;
-       while ((*In)!=0 && i < MaxLength)
-         {
-            Out[i] = *In;
-            In++;
-            i++;
-         }
-       Out[i] = 0;
-       return(Out);
-     }
+  KERNEL_USER_TIMES Kut;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessTimes,
+                                    &Kut,
+                                    sizeof(Kut),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+
+  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);
 }
 
-WINBOOL STDCALL CreateProcessA(LPCSTR lpApplicationName,
-                              LPSTR lpCommandLine,
-                              LPSECURITY_ATTRIBUTES lpProcessAttributes,
-                              LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                              WINBOOL bInheritHandles,
-                              DWORD dwCreationFlags,
-                              LPVOID lpEnvironment,
-                              LPCSTR lpCurrentDirectory,
-                              LPSTARTUPINFO lpStartupInfo,
-                              LPPROCESS_INFORMATION lpProcessInformation)
-/*
- * FUNCTION: The CreateProcess function creates a new process and its
- * primary thread. The new process executes the specified executable file
- * ARGUMENTS:
- * 
- *     lpApplicationName = Pointer to name of executable module
- *     lpCommandLine = Pointer to command line string
- *     lpProcessAttributes = Process security attributes
- *     lpThreadAttributes = Thread security attributes
- *     bInheritHandles = Handle inheritance flag
- *     dwCreationFlags = Creation flags
- *     lpEnvironment = Pointer to new environment block
- *     lpCurrentDirectory = Pointer to current directory name
- *     lpStartupInfo = Pointer to startup info
- *     lpProcessInformation = Pointer to process information
- */
-{
-   WCHAR ApplicationNameW[MAX_PATH];
-   WCHAR CommandLineW[MAX_PATH];
-   WCHAR CurrentDirectoryW[MAX_PATH];
-   PWSTR PApplicationNameW;
-   PWSTR PCommandLineW;
-   PWSTR PCurrentDirectoryW;
-   ULONG i;
-   
-   DPRINT("CreateProcessA\n");
-   
-   PApplicationNameW = InternalAnsiToUnicode(ApplicationNameW,
-                                            lpApplicationName,                                      
-                                            MAX_PATH);
-   PCommandLineW = InternalAnsiToUnicode(CommandLineW,
-                                        lpCommandLine,
-                                        MAX_PATH);
-   PCurrentDirectoryW = InternalAnsiToUnicode(CurrentDirectoryW,
-                                             lpCurrentDirectory,
-                                             MAX_PATH);        
-   return CreateProcessW(PApplicationNameW,
-                        PCommandLineW, 
-                        lpProcessAttributes,
-                        lpThreadAttributes,
-                        bInheritHandles,
-                        dwCreationFlags,
-                        lpEnvironment,
-                        PCurrentDirectoryW,
-                        lpStartupInfo,
-                        lpProcessInformation);                         
-}
-
-HANDLE STDCALL CreateFirstThread(HANDLE hProcess,
-                                LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                                DWORD dwStackSize,
-                                LPTHREAD_START_ROUTINE lpStartAddress,
-                                LPVOID lpParameter,
-                                DWORD dwCreationFlags,
-                                LPDWORD lpThreadId,
-                                PWSTR lpCommandLine)
-{      
-   NTSTATUS errCode;
-   HANDLE ThreadHandle;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   CLIENT_ID ClientId;
-   CONTEXT ThreadContext;
-   INITIAL_TEB InitialTeb;
-   BOOLEAN CreateSuspended = FALSE;
-   ULONG BaseAddress;
-   ULONG BytesWritten;
-   ULONG Temp;
-   ULONG CommandLineLen;
-   
-   if (lpCommandLine == NULL)
-     {
-       lpCommandLine = "";
-       CommandLineLen = 1;
-     }
-   else
-     {
-       CommandLineLen = wcslen(lpCommandLine) + 1;     
-     }
-   CommandLineLen = CommandLineLen * sizeof(WCHAR);
-   CommandLineLen = (CommandLineLen & (~0x3)) + 4;
-   DPRINT("CommandLineLen %d\n",CommandLineLen);
-   
-   
-   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;
-
-   BaseAddress = 0;
-   ZwAllocateVirtualMemory(hProcess,
-                          &BaseAddress,
-                          0,
-                           &dwStackSize,
-                          MEM_COMMIT,
-                          PAGE_READWRITE);
-   
 
-   memset(&ThreadContext,0,sizeof(CONTEXT));
-   ThreadContext.Eip = lpStartAddress;
-   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 = BaseAddress + dwStackSize - CommandLineLen - 8;   
-   ThreadContext.EFlags = (1<<1) + (1<<9);
-
-   NtWriteVirtualMemory(hProcess,
-                       BaseAddress + dwStackSize - CommandLineLen,
-                       lpCommandLine,
-                       CommandLineLen,
-                       &BytesWritten);
-   Temp = BaseAddress + dwStackSize - CommandLineLen;
-   NtWriteVirtualMemory(hProcess,
-                       BaseAddress + dwStackSize - CommandLineLen - 4,
-                       &Temp,
-                       sizeof(Temp),
-                       &BytesWritten);
-
-   errCode = NtCreateThread(&ThreadHandle,
-                           THREAD_ALL_ACCESS,
-                           &ObjectAttributes,
-                           hProcess,
-                           &ClientId,
-                           &ThreadContext,
-                           &InitialTeb,
-                           CreateSuspended);
-   if ( lpThreadId != NULL )
-     memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
-   
-   return ThreadHandle;
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+GetCurrentProcess(VOID)
+{
+  return((HANDLE)NtCurrentProcess());
 }
 
 
-WINBOOL STDCALL CreateProcessW(LPCWSTR lpApplicationName,
-                              LPWSTR lpCommandLine,
-                              LPSECURITY_ATTRIBUTES lpProcessAttributes,
-                              LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                              WINBOOL bInheritHandles,
-                              DWORD dwCreationFlags,
-                              LPVOID lpEnvironment,
-                              LPCWSTR lpCurrentDirectory,
-                              LPSTARTUPINFO lpStartupInfo,
-                              LPPROCESS_INFORMATION lpProcessInformation)
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+GetCurrentThread(VOID)
 {
-   HANDLE hFile, hSection, hProcess, hThread;
-   KPRIORITY PriorityClass;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   IO_STATUS_BLOCK IoStatusBlock;
-   BOOLEAN CreateSuspended;
-   NTSTATUS errCode;
-   UNICODE_STRING ApplicationNameString;
-   LPTHREAD_START_ROUTINE  lpStartAddress = NULL;
-   LPVOID  lpParameter = NULL;
-   PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
-   WCHAR TempApplicationName[256];
-   WCHAR TempFileName[256];
-   WCHAR TempDirectoryName[256];
-   WCHAR TempCommandLine[256];
-   ULONG i;
-   ULONG BaseAddress;
-   ULONG Size;
-   LARGE_INTEGER SectionOffset;
-   
-   DPRINT("CreateProcessW(lpApplicationName '%w', lpCommandLine '%w')\n",
-          lpApplicationName,lpCommandLine);
-   
-   wcscpy(TempCommandLine, lpCommandLine);
-   
-   hFile = NULL;
-   
-   /*
-    * Find the application name
-    */   
-   TempApplicationName[0] = '\\';
-   TempApplicationName[1] = '?';
-   TempApplicationName[2] = '?';
-   TempApplicationName[3] = '\\';
-   TempApplicationName[4] = 0;
-   
-   DPRINT("TempApplicationName '%w'\n",TempApplicationName);
-            
-   if (lpApplicationName != NULL)
-     {
-       wcscpy(TempFileName, lpApplicationName);
-       
-       DPRINT("TempFileName '%w'\n",TempFileName);
-     }
-   else
-     { 
-       wcscpy(TempFileName, lpCommandLine);
-       
-       DPRINT("TempFileName '%w'\n",TempFileName);
-       
-       for (i=0; TempFileName[i]!=' ' && TempFileName[i] != 0; i++);
-       TempFileName[i]=0;
-       
-     }
-   if (TempFileName[1] != ':')
-     {
-       GetCurrentDirectoryW(MAX_PATH,TempDirectoryName);
-       wcscat(TempApplicationName,TempDirectoryName);
-     }
-   wcscat(TempApplicationName,TempFileName);
-   
-   RtlInitUnicodeString(&ApplicationNameString, TempApplicationName);
-   
-   DPRINT("ApplicationName %w\n",ApplicationNameString.Buffer);
-   
-   InitializeObjectAttributes(&ObjectAttributes,
-                             &ApplicationNameString,
-                             OBJ_CASE_INSENSITIVE,
-                             NULL,
-                             SecurityDescriptor);
-
-   /*
-    * Try to open the executable
-    */
-   
-   errCode = NtOpenFile(&hFile,
-                       SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
-                       &ObjectAttributes,
-                       &IoStatusBlock,
-                       FILE_SHARE_DELETE|FILE_SHARE_READ,
-                       FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
-   
-   if ( !NT_SUCCESS(errCode) ) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
+  return((HANDLE)NtCurrentThread());
+}
 
-   errCode = NtCreateSection(&hSection,
-                            SECTION_ALL_ACCESS,
-                            NULL,
-                            NULL,
-                            PAGE_EXECUTE,
-                            SEC_IMAGE,
-                            hFile);
-   NtClose(hFile);
 
-   if ( !NT_SUCCESS(errCode) ) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-                       
-   errCode = NtCreateProcess(&hProcess,
-                            PROCESS_ALL_ACCESS, 
-                            NULL,
-                            NtCurrentProcess(),
-                            bInheritHandles,
-                            NULL,
-                            NULL,
-                            NULL);
-   
-   BaseAddress = (PVOID)0x10000;
-   LARGE_INTEGER_QUAD_PART(SectionOffset) = 0;
-   Size = 0x10000;
-   NtMapViewOfSection(hSection,
-                     hProcess,
-                     &BaseAddress,
-                     0,
-                      Size,
-                     &SectionOffset,
-                     &Size,
-                     0,
-                     MEM_COMMIT,
-                     PAGE_READWRITE);
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCurrentProcessId(VOID)
+{
+  return((DWORD)GetTeb()->Cid.UniqueProcess);
+}
 
-   
-   NtClose(hSection);
 
-   if ( !NT_SUCCESS(errCode) ) 
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetExitCodeProcess(HANDLE hProcess,
+                  LPDWORD lpExitCode)
+{
+  PROCESS_BASIC_INFORMATION ProcessBasic;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessBasicInformation,
+                                    &ProcessBasic,
+                                    sizeof(PROCESS_BASIC_INFORMATION),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
      }
-   
-#if 0
-   PriorityClass = NORMAL_PRIORITY_CLASS;      
-   NtSetInformationProcess(hProcess,
-                          ProcessBasePriority,
-                          &PriorityClass,
-                          sizeof(KPRIORITY));
-#endif
-   
-   DPRINT("Creating thread for process\n");
-   lpStartAddress = BaseAddress;
-   hThread =  CreateFirstThread(hProcess,      
-                               lpThreadAttributes,
-                               16384, // 3 page ??
-                               lpStartAddress, 
-                               lpParameter,    
-                               dwCreationFlags,
-                               &lpProcessInformation->dwThreadId,
-                               TempCommandLine);
-
-   if ( hThread == NULL )
-     return FALSE;
-      
-   lpProcessInformation->hProcess = hProcess;
-   lpProcessInformation->hThread = hThread;
 
-   GetProcessId(hProcess,&lpProcessInformation->dwProcessId);
+  memcpy(lpExitCode, &ProcessBasic.ExitStatus, sizeof(DWORD));
 
-   return TRUE;                                
+  return(TRUE);
 }
 
 
+/*
+ * @implemented
+ */
+DWORD
+STDCALL
+GetProcessId(HANDLE Process)
+{
+  PROCESS_BASIC_INFORMATION ProcessBasic;
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(Process,
+                                    ProcessBasicInformation,
+                                    &ProcessBasic,
+                                    sizeof(PROCESS_BASIC_INFORMATION),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return 0;
+  }
+
+  return ProcessBasic.UniqueProcessId;
+}
+
 
-HANDLE STDCALL OpenProcess(DWORD dwDesiredAccess,
-                          WINBOOL bInheritHandle,
-                          DWORD dwProcessId)
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+OpenProcess(DWORD dwDesiredAccess,
+           BOOL bInheritHandle,
+           DWORD dwProcessId)
 {
    NTSTATUS errCode;
    HANDLE ProcessHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;
-   CLIENT_ID ClientId ;
+   CLIENT_ID ClientId;
    
    ClientId.UniqueProcess = (HANDLE)dwProcessId;
+   ClientId.UniqueThread = INVALID_HANDLE_VALUE;
+   
    ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
    ObjectAttributes.RootDirectory = (HANDLE)NULL;
    ObjectAttributes.SecurityDescriptor = NULL;
    ObjectAttributes.SecurityQualityOfService = NULL;
+   ObjectAttributes.ObjectName = NULL;
    
-   if ( bInheritHandle == TRUE )
+   if (bInheritHandle == TRUE)
      ObjectAttributes.Attributes = OBJ_INHERIT;
    else
      ObjectAttributes.Attributes = 0;
    
-   errCode = NtOpenProcess(&ProcessHandle, 
-                          dwDesiredAccess, 
-                          &ObjectAttributes, 
+   errCode = NtOpenProcess(&ProcessHandle,
+                          dwDesiredAccess,
+                          &ObjectAttributes,
                           &ClientId);
-   if (!NT_SUCCESS(errCode)) 
+   if (!NT_SUCCESS(errCode))
      {
-       SetLastError(RtlNtStatusToDosError(errCode));
+       SetLastErrorByStatus (errCode);
        return NULL;
      }
    return ProcessHandle;
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-UINT WinExec (LPCSTR  lpCmdLine, UINT  uCmdShow)
+/*
+ * @implemented
+ */
+UINT STDCALL
+WinExec(LPCSTR lpCmdLine,
+       UINT uCmdShow)
 {
-   STARTUPINFO StartupInfo;
-   PROCESS_INFORMATION  ProcessInformation;    
-   HINSTANCE hInst;
+   STARTUPINFOA StartupInfo;
+   PROCESS_INFORMATION  ProcessInformation;
    DWORD dosErr;
 
-   StartupInfo.cb = sizeof(STARTUPINFO);
-   StartupInfo.wShowWindow = uCmdShow ;
+   RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
+   StartupInfo.cb = sizeof(STARTUPINFOA);
+   StartupInfo.wShowWindow = uCmdShow;
    StartupInfo.dwFlags = 0;
-   
-   hInst = (HINSTANCE)CreateProcessA(NULL,
-                                    (PVOID)lpCmdLine,
-                                    NULL,
-                                    NULL,
-                                    FALSE,
-                                    0,
-                                    NULL,
-                                    NULL,
-                                    &StartupInfo, 
-                                    &ProcessInformation);
-   if ( hInst == NULL ) 
+
+   if (! CreateProcessA(NULL,
+                       (PVOID)lpCmdLine,
+                       NULL,
+                       NULL,
+                       FALSE,
+                       0,
+                       NULL,
+                       NULL,
+                       &StartupInfo,
+                       &ProcessInformation))
      {
        dosErr = GetLastError();
-       return dosErr;
+       return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
+     }
+   if (NULL != lpfnGlobalRegisterWaitForInputIdle)
+     {
+       lpfnGlobalRegisterWaitForInputIdle (
+         ProcessInformation.hProcess,
+          10000
+       );
      }
-   if ( lpfnGlobalRegisterWaitForInputIdle != NULL )
-     lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,10000);
    NtClose(ProcessInformation.hProcess);
    NtClose(ProcessInformation.hThread);
-   return 0;   
-}
 
+   return 33; /* Something bigger than 31 means success. */
+}
 
 
-VOID RegisterWaitForInputIdle(WaitForInputIdleType  lpfnRegisterWaitForInputIdle)
+/*
+ * @implemented
+ */
+VOID STDCALL
+RegisterWaitForInputIdle (
+       WaitForInputIdleType    lpfnRegisterWaitForInputIdle
+       )
 {
-       lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle; 
+       lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
        return;
 }
 
-DWORD STDCALL WaitForInputIdle(HANDLE hProcess,        
-                              DWORD dwMilliseconds)
+
+/*
+ * @unimplemented
+ */
+DWORD STDCALL
+WaitForInputIdle (
+       HANDLE  hProcess,
+       DWORD   dwMilliseconds
+       )
 {
-   return 0;
+       return 0;
 }
 
-VOID 
-STDCALL
-Sleep(
-    DWORD dwMilliseconds       
-   )
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+Sleep(DWORD dwMilliseconds)
+{
+  SleepEx(dwMilliseconds, FALSE);
+  return;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SleepEx(DWORD dwMilliseconds,
+       BOOL bAlertable)
 {
-       SleepEx(dwMilliseconds,FALSE);
+  TIME Interval;
+  NTSTATUS errCode;
+  
+  if (dwMilliseconds != INFINITE)
+    {
+      /*
+       * System time units are 100 nanoseconds (a nanosecond is a billionth of
+       * a second).
+       */
+      Interval.QuadPart = -((ULONGLONG)dwMilliseconds * 10000);
+    }  
+  else
+    {
+      /* Approximately 292000 years hence */
+      Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL;
+    }
+
+  errCode = NtDelayExecution (bAlertable, &Interval);
+  if (!NT_SUCCESS(errCode))
+    {
+      SetLastErrorByStatus (errCode);
+      return -1;
+    }
+  return 0;
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
+{
+  PRTL_USER_PROCESS_PARAMETERS Params;
+
+  if (lpStartupInfo == NULL)
+    {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return;
+    }
+
+  Params = NtCurrentPeb()->ProcessParameters;
+
+  lpStartupInfo->cb = sizeof(STARTUPINFOW);
+  lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
+  lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
+  lpStartupInfo->dwX = Params->dwX;
+  lpStartupInfo->dwY = Params->dwY;
+  lpStartupInfo->dwXSize = Params->dwXSize;
+  lpStartupInfo->dwYSize = Params->dwYSize;
+  lpStartupInfo->dwXCountChars = Params->dwXCountChars;
+  lpStartupInfo->dwYCountChars = Params->dwYCountChars;
+  lpStartupInfo->dwFillAttribute = Params->dwFillAttribute;
+  lpStartupInfo->dwFlags = Params->dwFlags;
+  lpStartupInfo->wShowWindow = Params->wShowWindow;
+  lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
+  lpStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
+  lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
+
+  lpStartupInfo->hStdInput = Params->hStdInput;
+  lpStartupInfo->hStdOutput = Params->hStdOutput;
+  lpStartupInfo->hStdError = Params->hStdError;
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
+{
+  PRTL_USER_PROCESS_PARAMETERS Params;
+  ANSI_STRING AnsiString;
+
+  if (lpStartupInfo == NULL)
+    {
+       SetLastError(ERROR_INVALID_PARAMETER);
        return;
+    }
+
+  Params = NtCurrentPeb ()->ProcessParameters;
+
+  RtlAcquirePebLock ();
+
+  if (lpLocalStartupInfo == NULL)
+    {
+       /* create new local startup info (ansi) */
+       lpLocalStartupInfo = RtlAllocateHeap (RtlGetProcessHeap (),
+                                             0,
+                                             sizeof(STARTUPINFOA));
+
+       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->dwX;
+       lpLocalStartupInfo->dwY = Params->dwY;
+       lpLocalStartupInfo->dwXSize = Params->dwXSize;
+       lpLocalStartupInfo->dwYSize = Params->dwYSize;
+       lpLocalStartupInfo->dwXCountChars = Params->dwXCountChars;
+       lpLocalStartupInfo->dwYCountChars = Params->dwYCountChars;
+       lpLocalStartupInfo->dwFillAttribute = Params->dwFillAttribute;
+       lpLocalStartupInfo->dwFlags = Params->dwFlags;
+       lpLocalStartupInfo->wShowWindow = Params->wShowWindow;
+       lpLocalStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
+       lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
+
+       lpLocalStartupInfo->hStdInput = Params->hStdInput;
+       lpLocalStartupInfo->hStdOutput = Params->hStdOutput;
+       lpLocalStartupInfo->hStdError = Params->hStdError;
+     }
+
+   RtlReleasePebLock ();
+
+   /* copy local startup info data to external startup info */
+   memcpy (lpStartupInfo,
+           lpLocalStartupInfo,
+           sizeof(STARTUPINFOA));
 }
 
-DWORD 
-STDCALL
-SleepEx(
-    DWORD dwMilliseconds,      
-    BOOL bAlertable    
-   )
-{
-       TIME Interval;
-       NTSTATUS errCode;       
-
-       Interval.LowPart = dwMilliseconds * 1000;
-       Interval.HighPart = 0;
-       errCode = NtDelayExecution(bAlertable,&Interval);
-       if ( !NT_SUCCESS(errCode) ) {
-               SetLastError(RtlNtStatusToDosError(errCode));
-               return -1;
-       }
-       return 0;
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+FlushInstructionCache (HANDLE  hProcess,
+                      LPCVOID  lpBaseAddress,
+                      DWORD    dwSize)
+{
+  NTSTATUS Status;
+  
+  Status = NtFlushInstructionCache(hProcess,
+                                  (PVOID)lpBaseAddress,
+                                  dwSize);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+  return TRUE;
 }
 
 
+/*
+ * @implemented
+ */
+VOID STDCALL
+ExitProcess(UINT uExitCode)
+{
+  CSRSS_API_REQUEST CsrRequest;
+  CSRSS_API_REPLY CsrReply;
+  NTSTATUS Status;
+  
+  /* unload all dll's */
+  LdrShutdownProcess ();
+
+  /* notify csrss of process termination */
+  CsrRequest.Type = CSRSS_TERMINATE_PROCESS;
+  Status = CsrClientCallServer(&CsrRequest, 
+                              &CsrReply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
+    {
+      DPRINT("Failed to tell csrss about terminating process\n");
+    }
+  
+  
+  NtTerminateProcess (NtCurrentProcess (),
+                     uExitCode);
 
+  /* should never get here */
+  ASSERT(0);
+  while(1);
+}
 
 
-VOID
-STDCALL
-GetStartupInfoW(
-    LPSTARTUPINFO  lpStartupInfo       
-   )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+TerminateProcess (HANDLE       hProcess,
+                 UINT  uExitCode)
 {
-       NT_PEB *pPeb = GetCurrentPeb();
+  NTSTATUS Status;
+
+  Status = NtTerminateProcess (hProcess, uExitCode);
+  if (NT_SUCCESS(Status))
+    {
+      return TRUE;
+    }
+  SetLastErrorByStatus (Status);
+  return FALSE;
+}
 
-       if (lpStartupInfo == NULL ) {
-               SetLastError(ERROR_INVALID_PARAMETER);
-               return;
-       }
 
-       lpStartupInfo->cb = sizeof(STARTUPINFO);
-       lstrcpyW(lpStartupInfo->lpDesktop, pPeb->StartupInfo->Desktop); 
-       lstrcpyW(lpStartupInfo->lpTitle, pPeb->StartupInfo->Title);
-       lpStartupInfo->dwX = pPeb->StartupInfo->dwX; 
-       lpStartupInfo->dwY = pPeb->StartupInfo->dwY; 
-       lpStartupInfo->dwXSize = pPeb->StartupInfo->dwXSize; 
-       lpStartupInfo->dwYSize = pPeb->StartupInfo->dwYSize; 
-       lpStartupInfo->dwXCountChars = pPeb->StartupInfo->dwXCountChars; 
-       lpStartupInfo->dwYCountChars = pPeb->StartupInfo->dwYCountChars; 
-       lpStartupInfo->dwFillAttribute = pPeb->StartupInfo->dwFillAttribute; 
-       lpStartupInfo->dwFlags = pPeb->StartupInfo->dwFlags; 
-       lpStartupInfo->wShowWindow = pPeb->StartupInfo->wShowWindow; 
-       //lpStartupInfo->cbReserved2 = pPeb->StartupInfo->cbReserved; 
-       //lpStartupInfo->lpReserved = pPeb->StartupInfo->lpReserved1; 
-       //lpStartupInfo->lpReserved2 = pPeb->StartupInfo->lpReserved2; 
-       
-       lpStartupInfo->hStdInput = pPeb->StartupInfo->hStdInput; 
-       lpStartupInfo->hStdOutput = pPeb->StartupInfo->hStdOutput; 
-       lpStartupInfo->hStdError = pPeb->StartupInfo->hStdError; 
-       
-       
-       
-       return;
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+FatalAppExitA (UINT    uAction,
+              LPCSTR   lpMessageText)
+{
+  UNICODE_STRING MessageTextU;
+  ANSI_STRING MessageText;
   
+  RtlInitAnsiString (&MessageText, (LPSTR) lpMessageText);
+
+  RtlAnsiStringToUnicodeString (&MessageTextU,
+                               &MessageText,
+                               TRUE);
 
+  FatalAppExitW (uAction, MessageTextU.Buffer);
 
+  RtlFreeUnicodeString (&MessageTextU);
 }
 
 
-VOID
-STDCALL
-GetStartupInfoA(
-    LPSTARTUPINFO  lpStartupInfo       
-   )
-{
-       NT_PEB *pPeb = GetCurrentPeb();
-       ULONG i = 0;
-       if (lpStartupInfo == NULL ) {
-               SetLastError(ERROR_INVALID_PARAMETER);
-               return;
-       }
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+FatalAppExitW(UINT uAction,
+             LPCWSTR lpMessageText)
+{
+  return;
+}
+
 
-       
-       lpStartupInfo->cb = sizeof(STARTUPINFO);
-       i = 0;
+/*
+ * @implemented
+ */
+VOID STDCALL
+FatalExit (int ExitCode)
+{
+  ExitProcess(ExitCode);
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetPriorityClass (HANDLE hProcess)
+{
+  NTSTATUS Status;
+  PROCESS_PRIORITY_CLASS PriorityClass;
   
-       while ((pPeb->StartupInfo->Desktop[i])!=0 && i < MAX_PATH)
-       {
-               lpStartupInfo->lpDesktop[i] = (unsigned char)pPeb->StartupInfo->Desktop[i];
-               i++;
-       }
-       lpStartupInfo->lpDesktop[i] = 0;
-       
-        i = 0;
-       while ((pPeb->StartupInfo->Title[i])!=0 && i < MAX_PATH)
-       {
-               lpStartupInfo->lpTitle[i] = (unsigned char)pPeb->StartupInfo->Title[i];
-               i++;
-       }
-       lpStartupInfo->lpTitle[i] = 0;
-
-       lpStartupInfo->dwX = pPeb->StartupInfo->dwX; 
-       lpStartupInfo->dwY = pPeb->StartupInfo->dwY; 
-       lpStartupInfo->dwXSize = pPeb->StartupInfo->dwXSize; 
-       lpStartupInfo->dwYSize = pPeb->StartupInfo->dwYSize; 
-       lpStartupInfo->dwXCountChars = pPeb->StartupInfo->dwXCountChars; 
-       lpStartupInfo->dwYCountChars = pPeb->StartupInfo->dwYCountChars; 
-       lpStartupInfo->dwFillAttribute = pPeb->StartupInfo->dwFillAttribute; 
-       lpStartupInfo->dwFlags = pPeb->StartupInfo->dwFlags; 
-       lpStartupInfo->wShowWindow = pPeb->StartupInfo->wShowWindow; 
-       //lpStartupInfo->cbReserved2 = pPeb->StartupInfo->cbReserved; 
-       //lpStartupInfo->lpReserved = pPeb->StartupInfo->lpReserved1; 
-       //lpStartupInfo->lpReserved2 = pPeb->StartupInfo->lpReserved2; 
-       
-       lpStartupInfo->hStdInput = pPeb->StartupInfo->hStdInput; 
-       lpStartupInfo->hStdOutput = pPeb->StartupInfo->hStdOutput; 
-       lpStartupInfo->hStdError = pPeb->StartupInfo->hStdError; 
-       
-       return;
+  Status = NtQueryInformationProcess(hProcess,
+                                     ProcessPriorityClass,
+                                     &PriorityClass,
+                                     sizeof(PROCESS_PRIORITY_CLASS),
+                                     NULL);
+  if(NT_SUCCESS(Status))
+  {
+    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_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;
+    }
+  }
+  
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
-BOOL 
-STDCALL
-FlushInstructionCache(
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetPriorityClass (HANDLE hProcess,
+                 DWORD dwPriorityClass)
+{
+  NTSTATUS Status;
+  PROCESS_PRIORITY_CLASS PriorityClass;
+  
+  switch(dwPriorityClass)
+  {
+    case IDLE_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
+      break;
+
+    case BELOW_NORMAL_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
+      break;
+
+    case NORMAL_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
+      break;
+
+    case ABOVE_NORMAL_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
+      break;
+
+    case HIGH_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
+      break;
+
+    case REALTIME_PRIORITY_CLASS:
+      PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
+      break;
+
+    default:
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return FALSE;
+  }
   
+  PriorityClass.Foreground = FALSE;
+
+  Status = NtSetInformationProcess(hProcess,
+                                   ProcessPriorityClass,
+                                   &PriorityClass,
+                                   sizeof(PROCESS_PRIORITY_CLASS));
+
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return FALSE;
+  }
+  
+  return TRUE;
+}
 
-    HANDLE  hProcess,  
-    LPCVOID  lpBaseAddress,    
-    DWORD  dwSize      
-   )
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetProcessVersion (DWORD ProcessId)
 {
-       NTSTATUS errCode;
-       errCode = NtFlushInstructionCache(hProcess,(PVOID)lpBaseAddress,dwSize);
-       if ( !NT_SUCCESS(errCode) ) {
-               SetLastError(RtlNtStatusToDosError(errCode));
-               return FALSE;
+  DWORD                        Version = 0;
+  PIMAGE_NT_HEADERS    NtHeader = NULL;
+  PVOID                        BaseAddress = NULL;
+
+  /* Caller's */
+  if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
+    {
+      BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
+      NtHeader = RtlImageNtHeader (BaseAddress);
+      if (NULL != NtHeader)
+       {
+         Version =
+           (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) | 
+           (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
        }
-       return TRUE;
+    }
+  else /* other process */
+    {
+      /* FIXME: open the other process */
+      SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    }
+  return (Version);
 }
 
-VOID STDCALL ExitProcess(UINT uExitCode) 
-{      
-   NtTerminateProcess(NtCurrentProcess() ,uExitCode);
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetProcessIoCounters(
+  HANDLE hProcess,
+  PIO_COUNTERS lpIoCounters)
+{
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessIoCounters,
+                                    lpIoCounters,
+                                    sizeof(IO_COUNTERS),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+  
+  return TRUE;
 }
 
-VOID
+
+/*
+ * @implemented
+ */
+BOOL
 STDCALL
-FatalAppExitA(
-             UINT uAction,
-             LPCSTR lpMessageText
-             )
+GetProcessPriorityBoost(HANDLE hProcess,
+                        PBOOL pDisablePriorityBoost)
 {
-       WCHAR MessageTextW[MAX_PATH];
-       UINT i;
-       i = 0;
-       while ((*lpMessageText)!=0 && i < 35)
-       {
-               MessageTextW[i] = *lpMessageText;
-               lpMessageText++;
-               i++;
-       }
-       MessageTextW[i] = 0;
-       
-       return FatalAppExitW(uAction,MessageTextW);
+  NTSTATUS Status;
+  BOOL PriorityBoost;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessPriorityBoost,
+                                    &PriorityBoost,
+                                    sizeof(BOOL),
+                                    NULL);
+  if (NT_SUCCESS(Status))
+    {
+      *pDisablePriorityBoost = PriorityBoost;
+      return TRUE;
+    }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
-       
-VOID STDCALL FatalAppExitW(UINT uAction, LPCWSTR lpMessageText)
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+SetProcessPriorityBoost(HANDLE hProcess,
+                        BOOL bDisablePriorityBoost)
 {
-   return;     
+  NTSTATUS Status;
+  BOOL PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
+
+  Status = NtSetInformationProcess(hProcess,
+                                  ProcessPriorityBoost,
+                                  &PriorityBoost,
+                                  sizeof(BOOL));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
 
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetProcessHandleCount(HANDLE hProcess,
+                      PDWORD pdwHandleCount)
+{
+    ULONG phc;
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessHandleCount,
+                                       &phc,
+                                       sizeof(ULONG),
+                                       NULL);
+    if(NT_SUCCESS(Status))
+    {
+      *pdwHandleCount = phc;
+      return TRUE;
+    }
+
+    SetLastErrorByStatus(Status);
+    return FALSE;
+}
+
+/* EOF */