Use ASSERT() instead of assert().
[reactos.git] / reactos / lib / kernel32 / process / proc.c
index c1521d3..7cc029c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: proc.c,v 1.27 2000/01/20 22:56:49 ekohl Exp $
+/* $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
 
 /* INCLUDES ****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <windows.h>
-#include <kernel32/proc.h>
-#include <kernel32/thread.h>
-#include <wchar.h>
-#include <string.h>
-#include <internal/i386/segment.h>
-#include <internal/teb.h>
+#include <k32.h>
 
 #define NDEBUG
-#include <kernel32/kernel32.h>
+#include "../include/debug.h"
+
 
 /* GLOBALS *******************************************************************/
 
 WaitForInputIdleType  lpfnGlobalRegisterWaitForInputIdle;
 
-VOID
-STDCALL
-RegisterWaitForInputIdle (
-       WaitForInputIdleType    lpfnRegisterWaitForInputIdle
-       );
+LPSTARTUPINFOA lpLocalStartupInfo = NULL;
+
+VOID STDCALL
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
 
 /* FUNCTIONS ****************************************************************/
 
-WINBOOL
-STDCALL
-GetProcessId (
-       HANDLE  hProcess,
-       LPDWORD lpProcessId
-       );
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessAffinityMask (HANDLE hProcess,
+                       LPDWORD lpProcessAffinityMask,
+                       LPDWORD lpSystemAffinityMask)
+{
+  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;
+}
 
 
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessAffinityMask (HANDLE hProcess,
+                       DWORD dwProcessAffinityMask)
+{
+  NTSTATUS Status;
+
+  Status = NtSetInformationProcess (hProcess,
+                                   ProcessAffinityMask,
+                                   (PVOID)&dwProcessAffinityMask,
+                                   sizeof(DWORD));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus (Status);
+      return FALSE;
+    }
+
+  return TRUE;
+}
 
 
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessShutdownParameters (LPDWORD lpdwLevel,
+                             LPDWORD lpdwFlags)
+{
+  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);
+}
 
-WINBOOL
-STDCALL
-GetProcessTimes (
-       HANDLE          hProcess,
-       LPFILETIME      lpCreationTime,
-       LPFILETIME      lpExitTime,
-       LPFILETIME      lpKernelTime,
-       LPFILETIME      lpUserTime
-       )
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessShutdownParameters (DWORD dwLevel,
+                             DWORD dwFlags)
 {
-       DPRINT("GetProcessTimes is unimplemented\n");
-       return FALSE;
+  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);
 }
 
 
-HANDLE
-STDCALL
-GetCurrentProcess (VOID)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessWorkingSetSize (HANDLE hProcess,
+                         PSIZE_T lpMinimumWorkingSetSize,
+                         PSIZE_T lpMaximumWorkingSetSize)
 {
-       return (HANDLE) NtCurrentProcess();
+  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);
 }
 
 
-HANDLE
-STDCALL
-GetCurrentThread (VOID)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetProcessWorkingSetSize(HANDLE hProcess,
+                        SIZE_T dwMinimumWorkingSetSize,
+                        SIZE_T dwMaximumWorkingSetSize)
 {
-       return (HANDLE) NtCurrentThread();
+  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);
 }
 
 
-DWORD
-STDCALL
-GetCurrentProcessId (VOID)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetProcessTimes(HANDLE hProcess,
+               LPFILETIME lpCreationTime,
+               LPFILETIME lpExitTime,
+               LPFILETIME lpKernelTime,
+               LPFILETIME lpUserTime)
 {
-       return (DWORD) (GetTeb()->Cid).UniqueProcess;
+  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
-GetExitCodeProcess (
-       HANDLE  hProcess,
-       LPDWORD lpExitCode
-       )
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+GetCurrentProcess(VOID)
 {
-   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;        
+  return((HANDLE)NtCurrentProcess());
 }
 
 
-WINBOOL
-STDCALL
-GetProcessId (
-       HANDLE  hProcess,
-       LPDWORD lpProcessId 
-       )
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+GetCurrentThread(VOID)
 {
-   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;        
+  return((HANDLE)NtCurrentThread());
 }
 
 
-PWSTR
-InternalAnsiToUnicode (
-       PWSTR   Out,
-       LPCSTR  In,
-       ULONG   MaxLength
-       )
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetCurrentProcessId(VOID)
 {
-   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);
+  return((DWORD)GetTeb()->Cid.UniqueProcess);
+}
+
+
+/*
+ * @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);
      }
+
+  memcpy(lpExitCode, &ProcessBasic.ExitStatus, sizeof(DWORD));
+
+  return(TRUE);
 }
 
 
-HANDLE
+/*
+ * @implemented
+ */
+DWORD
 STDCALL
-OpenProcess (
-       DWORD   dwDesiredAccess,
-       WINBOOL bInheritHandle,
-       DWORD   dwProcessId
-       )
+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;
+}
+
+
+/*
+ * @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;
@@ -192,73 +346,82 @@ OpenProcess (
    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
-STDCALL
-WinExec (
-       LPCSTR  lpCmdLine,
-       UINT    uCmdShow
-       )
+/*
+ * @implemented
+ */
+UINT STDCALL
+WinExec(LPCSTR lpCmdLine,
+       UINT uCmdShow)
 {
    STARTUPINFOA StartupInfo;
    PROCESS_INFORMATION  ProcessInformation;
-   HINSTANCE hInst;
    DWORD dosErr;
-   
+
+   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
-STDCALL
+/*
+ * @implemented
+ */
+VOID STDCALL
 RegisterWaitForInputIdle (
        WaitForInputIdleType    lpfnRegisterWaitForInputIdle
        )
 {
-       lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle; 
+       lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
        return;
 }
 
 
-DWORD
-STDCALL
+/*
+ * @unimplemented
+ */
+DWORD STDCALL
 WaitForInputIdle (
-       HANDLE  hProcess,       
+       HANDLE  hProcess,
        DWORD   dwMilliseconds
        )
 {
@@ -266,208 +429,516 @@ WaitForInputIdle (
 }
 
 
-VOID STDCALL Sleep (DWORD dwMilliseconds)
+/*
+ * @implemented
+ */
+VOID STDCALL
+Sleep(DWORD dwMilliseconds)
 {
-   SleepEx (dwMilliseconds, FALSE);
-   return;
+  SleepEx(dwMilliseconds, FALSE);
+  return;
 }
 
-DWORD STDCALL SleepEx(DWORD    dwMilliseconds,
-                     BOOL      bAlertable)
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+SleepEx(DWORD dwMilliseconds,
+       BOOL bAlertable)
 {
-   TIME Interval;
-   NTSTATUS errCode;   
-   
-   Interval.QuadPart = dwMilliseconds * 1000;
-   
-   errCode = NtDelayExecution(bAlertable,&Interval);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return -1;
-     }
-   return 0;
+  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;
 }
 
 
-VOID
-STDCALL
-GetStartupInfoW (
-       LPSTARTUPINFOW  lpStartupInfo
-       )
+/*
+ * @implemented
+ */
+VOID STDCALL
+GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
 {
-   PRTL_USER_PROCESS_PARAMETERS Params;
+  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;
+}
 
-   Params = NtCurrentPeb()->ProcessParameters;
 
-   if (lpStartupInfo == NULL)
-     {
+/*
+ * @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;
      }
 
-   lpStartupInfo->cb = sizeof(STARTUPINFOW);
-   wcscpy (lpStartupInfo->lpDesktop, Params->DesktopInfo.Buffer);
-   wcscpy (lpStartupInfo->lpTitle, Params->WindowTitle.Buffer);
-   lpStartupInfo->dwX = Params->StartingX;
-   lpStartupInfo->dwY = Params->StartingY;
-   lpStartupInfo->dwXSize = Params->CountX;
-   lpStartupInfo->dwYSize = Params->CountY;
-   lpStartupInfo->dwXCountChars = Params->CountCharsX;
-   lpStartupInfo->dwYCountChars = Params->CountCharsY;
-   lpStartupInfo->dwFillAttribute = Params->FillAttribute;
-   lpStartupInfo->dwFlags = Params->WindowFlags;
-   lpStartupInfo->wShowWindow = Params->ShowWindowFlags;
-   wcscpy (lpStartupInfo->lpReserved, Params->ShellInfo.Buffer);
-//   lpStartupInfo->cbReserved2 = Params->cbReserved;
-//   lpStartupInfo->lpReserved2 = Params->lpReserved2;
-
-   lpStartupInfo->hStdInput = Params->StandardInput;
-   lpStartupInfo->hStdOutput = Params->StandardOutput;
-   lpStartupInfo->hStdError = Params->StandardError;
-}
-
-
-VOID
-STDCALL
-GetStartupInfoA (
-       LPSTARTUPINFOA  lpStartupInfo
-       )
+   RtlReleasePebLock ();
+
+   /* copy local startup info data to external startup info */
+   memcpy (lpStartupInfo,
+           lpLocalStartupInfo,
+           sizeof(STARTUPINFOA));
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+FlushInstructionCache (HANDLE  hProcess,
+                      LPCVOID  lpBaseAddress,
+                      DWORD    dwSize)
 {
-   PRTL_USER_PROCESS_PARAMETERS Params;
-   ULONG i = 0;
+  NTSTATUS Status;
+  
+  Status = NtFlushInstructionCache(hProcess,
+                                  (PVOID)lpBaseAddress,
+                                  dwSize);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+  return TRUE;
+}
 
-   Params = NtCurrentPeb()->ProcessParameters;
 
-   if (lpStartupInfo == NULL)
-     {
-       SetLastError(ERROR_INVALID_PARAMETER);
-       return;
-     }
+/*
+ * @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);
+}
 
-   lpStartupInfo->cb = sizeof(STARTUPINFOA);
-#if 0
-   i = 0;
-   while ((pPeb->Ppb->Desktop[i])!=0 && i < MAX_PATH)
-     {
-       lpStartupInfo->lpDesktop[i] = (unsigned char)
-         pPeb->Ppb->Desktop[i];
-       i++;
-     }
-   lpStartupInfo->lpDesktop[i] = 0;
 
-   i = 0;
-   while ((pPeb->Ppb->Title[i])!=0 && i < MAX_PATH)
-     {
-       lpStartupInfo->lpTitle[i] = (unsigned char)pPeb->ProcessParameters->Title[i];
-       i++;
-     }
-   lpStartupInfo->lpTitle[i] = 0;
-#endif
-   lpStartupInfo->dwX = Params->StartingX;
-   lpStartupInfo->dwY = Params->StartingY;
-   lpStartupInfo->dwXSize = Params->CountX;
-   lpStartupInfo->dwYSize = Params->CountY;
-   lpStartupInfo->dwXCountChars = Params->CountCharsX;
-   lpStartupInfo->dwYCountChars = Params->CountCharsY;
-   lpStartupInfo->dwFillAttribute = Params->FillAttribute;
-   lpStartupInfo->dwFlags = Params->WindowFlags;
-   lpStartupInfo->wShowWindow = Params->ShowWindowFlags;
-//   lpStartupInfo->cbReserved2 = Params->cbReserved;
-//   lpStartupInfo->lpReserved = Params->lpReserved1;
-//   lpStartupInfo->lpReserved2 = Params->lpReserved2;
-
-   lpStartupInfo->hStdInput = Params->StandardInput;
-   lpStartupInfo->hStdOutput = Params->StandardOutput;
-   lpStartupInfo->hStdError = Params->StandardError;
+/*
+ * @implemented
+ */
+BOOL STDCALL
+TerminateProcess (HANDLE       hProcess,
+                 UINT  uExitCode)
+{
+  NTSTATUS Status;
+
+  Status = NtTerminateProcess (hProcess, uExitCode);
+  if (NT_SUCCESS(Status))
+    {
+      return TRUE;
+    }
+  SetLastErrorByStatus (Status);
+  return FALSE;
 }
 
 
-BOOL
-STDCALL
-FlushInstructionCache (
-       HANDLE  hProcess,       
-       LPCVOID lpBaseAddress,  
-       DWORD   dwSize
-       )
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+FatalAppExitA (UINT    uAction,
+              LPCSTR   lpMessageText)
 {
-       NTSTATUS        errCode;
+  UNICODE_STRING MessageTextU;
+  ANSI_STRING MessageText;
+  
+  RtlInitAnsiString (&MessageText, (LPSTR) lpMessageText);
+
+  RtlAnsiStringToUnicodeString (&MessageTextU,
+                               &MessageText,
+                               TRUE);
 
-       errCode = NtFlushInstructionCache(
-                       hProcess,
-                       (PVOID) lpBaseAddress,
-                       dwSize
-                       );
-       if (!NT_SUCCESS(errCode))
+  FatalAppExitW (uAction, MessageTextU.Buffer);
+
+  RtlFreeUnicodeString (&MessageTextU);
+}
+
+
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+FatalAppExitW(UINT uAction,
+             LPCWSTR lpMessageText)
+{
+  return;
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+FatalExit (int ExitCode)
+{
+  ExitProcess(ExitCode);
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetPriorityClass (HANDLE hProcess)
+{
+  NTSTATUS Status;
+  PROCESS_PRIORITY_CLASS PriorityClass;
+  
+  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;
+}
+
+
+/*
+ * @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;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetProcessVersion (DWORD ProcessId)
+{
+  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)
        {
-               SetLastError(RtlNtStatusToDosError(errCode));
-               return FALSE;
+         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
+/*
+ * @implemented
+ */
+BOOL
 STDCALL
-ExitProcess (
-       UINT    uExitCode
-       )
+GetProcessIoCounters(
+  HANDLE hProcess,
+  PIO_COUNTERS lpIoCounters)
 {
-       NtTerminateProcess(
-               NtCurrentProcess(),
-               uExitCode
-               );
+  NTSTATUS Status;
+
+  Status = NtQueryInformationProcess(hProcess,
+                                    ProcessIoCounters,
+                                    lpIoCounters,
+                                    sizeof(IO_COUNTERS),
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return(FALSE);
+    }
+  
+  return TRUE;
 }
 
 
-WINBOOL
+/*
+ * @implemented
+ */
+BOOL
 STDCALL
-TerminateProcess (
-       HANDLE  hProcess,
-       UINT    uExitCode
-       )
+GetProcessPriorityBoost(HANDLE hProcess,
+                        PBOOL pDisablePriorityBoost)
 {
-   NTSTATUS errCode;
-   errCode = NtTerminateProcess(hProcess, uExitCode);
-   if (!NT_SUCCESS(errCode))
-     {
-       SetLastError(RtlNtStatusToDosError(errCode));
-       return FALSE;
-     }
-   return TRUE;
+  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
+
+/*
+ * @implemented
+ */
+BOOL
 STDCALL
-FatalAppExitA (
-       UINT    uAction,
-       LPCSTR  lpMessageText
-       )
+SetProcessPriorityBoost(HANDLE hProcess,
+                        BOOL bDisablePriorityBoost)
 {
-   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 = (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;
 }
 
 
-VOID
+/*
+ * @implemented
+ */
+BOOL
 STDCALL
-FatalAppExitW (
-       UINT    uAction,
-       LPCWSTR lpMessageText
-       )
+GetProcessHandleCount(HANDLE hProcess,
+                      PDWORD pdwHandleCount)
 {
-       return;
+    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 */