- Update to r53061
[reactos.git] / dll / win32 / kernel32 / client / proc.c
similarity index 64%
rename from dll/win32/kernel32/process/procsup.c
rename to dll/win32/kernel32/client/proc.c
index 39f7007..1ba1057 100644 (file)
@@ -1,10 +1,12 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
- * FILE:            lib/kernel32/process/create.c
+ * FILE:            lib/kernel32/proc/proc.c
  * PURPOSE:         Process functions
- * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
- *                  Ariadne ( ariadne@xs4all.nl)
+ * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
+ * UPDATE HISTORY:
+ *                  Created 01/11/98
  */
 
 /* INCLUDES ****************************************************************/
 #define NDEBUG
 #include <debug.h>
 
+
+typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
+
+/* GLOBALS *******************************************************************/
+
+static UNICODE_STRING CommandLineStringW;
+static ANSI_STRING CommandLineStringA;
+
+static BOOL bCommandLineInitialized = FALSE;
+
+WaitForInputIdleType  lpfnGlobalRegisterWaitForInputIdle;
+
+LPSTARTUPINFOA lpLocalStartupInfo = NULL;
+
+VOID WINAPI
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
+
 UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
-UNICODE_STRING BaseDefaultPath;
 PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
 
 #define CMD_STRING L"cmd /c "
@@ -25,7 +43,7 @@ VOID
 CALLBACK
 ConsoleControlDispatcher(DWORD CodeAndFlag);
 
-/* INTERNAL FUNCTIONS *******************************************************/
+/* FUNCTIONS ****************************************************************/
 
 static
 LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
@@ -872,7 +890,1281 @@ BasepInitializeEnvironment(HANDLE ProcessHandle,
     return STATUS_SUCCESS;
 }
 
-/* FUNCTIONS ****************************************************************/
+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);
+
+    CommandLineStringA.Buffer[CommandLineStringA.Length] = 0;
+
+    bCommandLineInitialized = TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessAffinityMask(HANDLE hProcess,
+                       PDWORD_PTR lpProcessAffinityMask,
+                       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;
+    }
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessBasicInformation,
+                                       (PVOID)&ProcessInfo,
+                                       sizeof(PROCESS_BASIC_INFORMATION),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask;
+    *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask;
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessAffinityMask(HANDLE hProcess,
+                       DWORD_PTR dwProcessAffinityMask)
+{
+    NTSTATUS Status;
+
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessAffinityMask,
+                                     (PVOID)&dwProcessAffinityMask,
+                                     sizeof(DWORD));
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessShutdownParameters(LPDWORD lpdwLevel,
+                             LPDWORD lpdwFlags)
+{
+    CSR_API_MESSAGE CsrRequest;
+    ULONG Request;
+    NTSTATUS Status;
+
+    Request = GET_SHUTDOWN_PARAMETERS;
+    Status = CsrClientCallServer(&CsrRequest,
+                                 NULL,
+                                 MAKE_CSR_API(Request, CSR_NATIVE),
+                                 sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level;
+    *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags;
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessShutdownParameters(DWORD dwLevel,
+                             DWORD dwFlags)
+{
+    CSR_API_MESSAGE CsrRequest;
+    ULONG Request;
+    NTSTATUS Status;
+
+    CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
+    CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
+
+    Request = SET_SHUTDOWN_PARAMETERS;
+    Status = CsrClientCallServer(&CsrRequest,
+                                 NULL,
+                                 MAKE_CSR_API(Request, CSR_NATIVE),
+                                 sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessWorkingSetSize(HANDLE hProcess,
+                         PSIZE_T lpMinimumWorkingSetSize,
+                         PSIZE_T lpMaximumWorkingSetSize)
+{
+    QUOTA_LIMITS QuotaLimits;
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessQuotaLimits,
+                                       &QuotaLimits,
+                                       sizeof(QUOTA_LIMITS),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize;
+    *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize;
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessWorkingSetSize(HANDLE hProcess,
+                         SIZE_T dwMinimumWorkingSetSize,
+                         SIZE_T dwMaximumWorkingSetSize)
+{
+    QUOTA_LIMITS QuotaLimits;
+    NTSTATUS Status;
+
+    QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
+    QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessQuotaLimits,
+                                     &QuotaLimits,
+                                     sizeof(QUOTA_LIMITS));
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessTimes(HANDLE hProcess,
+                LPFILETIME lpCreationTime,
+                LPFILETIME lpExitTime,
+                LPFILETIME lpKernelTime,
+                LPFILETIME lpUserTime)
+{
+    KERNEL_USER_TIMES Kut;
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessTimes,
+                                       &Kut,
+                                       sizeof(Kut),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(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;
+}
+
+
+/*
+ * @implemented
+ */
+HANDLE
+WINAPI
+GetCurrentProcess(VOID)
+{
+    return (HANDLE)NtCurrentProcess();
+}
+
+
+/*
+ * @implemented
+ */
+HANDLE
+WINAPI
+GetCurrentThread(VOID)
+{
+    return (HANDLE)NtCurrentThread();
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetCurrentProcessId(VOID)
+{
+    return HandleToUlong(GetTeb()->ClientId.UniqueProcess);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+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))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    *lpExitCode = (DWORD)ProcessBasic.ExitStatus;
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetProcessId(HANDLE Process)
+{
+    PROCESS_BASIC_INFORMATION ProcessBasic;
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(Process,
+                                       ProcessBasicInformation,
+                                       &ProcessBasic,
+                                       sizeof(PROCESS_BASIC_INFORMATION),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return 0;
+    }
+
+    return (DWORD)ProcessBasic.UniqueProcessId;
+}
+
+
+/*
+ * @implemented
+ */
+HANDLE
+WINAPI
+OpenProcess(DWORD dwDesiredAccess,
+            BOOL bInheritHandle,
+            DWORD dwProcessId)
+{
+    NTSTATUS errCode;
+    HANDLE ProcessHandle;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    CLIENT_ID ClientId;
+
+    ClientId.UniqueProcess = UlongToHandle(dwProcessId);
+    ClientId.UniqueThread = 0;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               NULL,
+                               (bInheritHandle ? OBJ_INHERIT : 0),
+                               NULL,
+                               NULL);
+
+    errCode = NtOpenProcess(&ProcessHandle,
+                            dwDesiredAccess,
+                            &ObjectAttributes,
+                            &ClientId);
+    if (!NT_SUCCESS(errCode))
+    {
+        BaseSetLastNTError(errCode);
+        return NULL;
+    }
+
+    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)
+{
+    lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
+    return;
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+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->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 = (WORD)Params->ShowWindowFlags;
+    lpStartupInfo->cbReserved2 = Params->RuntimeData.Length;
+    lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
+
+    lpStartupInfo->hStdInput = Params->StandardInput;
+    lpStartupInfo->hStdOutput = Params->StandardOutput;
+    lpStartupInfo->hStdError = Params->StandardError;
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
+{
+    PRTL_USER_PROCESS_PARAMETERS Params;
+    ANSI_STRING AnsiString;
+
+    if (lpStartupInfo == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return;
+    }
+
+    Params = NtCurrentPeb ()->ProcessParameters;
+
+    RtlAcquirePebLock ();
+
+    /* FIXME - not thread-safe */
+    if (lpLocalStartupInfo == NULL)
+    {
+        /* create new local startup info (ansi) */
+        lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+                                             0,
+                                             sizeof(STARTUPINFOA));
+        if (lpLocalStartupInfo == NULL)
+        {
+            RtlReleasePebLock();
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return;
+        }
+
+        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));
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+FlushInstructionCache(HANDLE hProcess,
+                      LPCVOID lpBaseAddress,
+                      SIZE_T dwSize)
+{
+    NTSTATUS Status;
+
+    Status = NtFlushInstructionCache(hProcess,
+                                     (PVOID)lpBaseAddress,
+                                     dwSize);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+ExitProcess(UINT uExitCode)
+{
+    CSR_API_MESSAGE CsrRequest;
+    ULONG Request;
+    NTSTATUS Status;
+
+    /* kill sibling threads ... we want to be alone at this point */
+    NtTerminateProcess(NULL, 0);
+
+    /* unload all dll's */
+    LdrShutdownProcess();
+
+    /* 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))
+    {
+        DPRINT("Failed to tell csrss about terminating process\n");
+    }
+
+    NtTerminateProcess(NtCurrentProcess (),
+                       uExitCode);
+
+    /* should never get here */
+    ASSERT(0);
+    while(1);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+TerminateProcess(HANDLE hProcess,
+                 UINT uExitCode)
+{
+    NTSTATUS Status;
+
+    if (hProcess == NULL)
+    {
+      return FALSE;
+    }
+
+    Status = NtTerminateProcess(hProcess, uExitCode);
+    if (NT_SUCCESS(Status))
+    {
+        return TRUE;
+    }
+
+    BaseSetLastNTError(Status);
+    return FALSE;
+}
+
+
+/*
+ * @unimplemented
+ */
+VOID
+WINAPI
+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);
+}
+
+
+/*
+ * @unimplemented
+ */
+VOID
+WINAPI
+FatalAppExitW(UINT uAction,
+              LPCWSTR lpMessageText)
+{
+    static const WCHAR szUser32[] = L"user32.dll\0";
+
+    HMODULE hModule = GetModuleHandleW(szUser32);
+    MessageBoxW_Proc pMessageBoxW = NULL;
+
+    DPRINT1("AppExit\n");
+
+    if (hModule)
+        pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW");
+
+    if (pMessageBoxW)
+        pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK);
+    else
+        DPRINT1("%s\n", lpMessageText);
+
+    ExitProcess(0);
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+FatalExit(int ExitCode)
+{
+    ExitProcess(ExitCode);
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+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;
+    }
+  }
+
+  BaseSetLastNTError(Status);
+  return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+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))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetProcessVersion(DWORD ProcessId)
+{
+    DWORD Version = 0;
+    PIMAGE_NT_HEADERS NtHeader = NULL;
+    IMAGE_NT_HEADERS NtHeaders;
+    IMAGE_DOS_HEADER DosHeader;
+    PROCESS_BASIC_INFORMATION ProcessBasicInfo;
+    PVOID BaseAddress = NULL;
+    HANDLE ProcessHandle = NULL;
+    NTSTATUS Status;
+    SIZE_T Count;
+    PEB Peb;
+
+    _SEH2_TRY
+    {
+        if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
+        {
+            /* Caller's */
+            BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
+            NtHeader = RtlImageNtHeader(BaseAddress);
+
+            Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
+                      (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
+        }
+        else
+        {
+            /* Other process */
+            ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
+                                        FALSE,
+                                        ProcessId);
+
+            if (!ProcessHandle) return 0;
+
+            Status = NtQueryInformationProcess(ProcessHandle,
+                                               ProcessBasicInformation,
+                                               &ProcessBasicInfo,
+                                               sizeof(ProcessBasicInfo),
+                                               NULL);
+
+            if (!NT_SUCCESS(Status)) goto Error;
+
+            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;
+
+            Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
+                               NtHeaders.OptionalHeader.MajorSubsystemVersion);
+
+Error:
+            if (!NT_SUCCESS(Status))
+            {
+                BaseSetLastNTError(Status);
+            }
+        }
+    }
+    _SEH2_FINALLY
+    {
+        if (ProcessHandle) CloseHandle(ProcessHandle);
+    }
+    _SEH2_END;
+
+    return Version;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessIoCounters(HANDLE hProcess,
+                     PIO_COUNTERS lpIoCounters)
+{
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessIoCounters,
+                                       lpIoCounters,
+                                       sizeof(IO_COUNTERS),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessPriorityBoost(HANDLE hProcess,
+                        PBOOL pDisablePriorityBoost)
+{
+    NTSTATUS Status;
+    ULONG PriorityBoost;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessPriorityBoost,
+                                       &PriorityBoost,
+                                       sizeof(ULONG),
+                                       NULL);
+    if (NT_SUCCESS(Status))
+    {
+        *pDisablePriorityBoost = PriorityBoost;
+        return TRUE;
+    }
+
+    BaseSetLastNTError(Status);
+    return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessPriorityBoost(HANDLE hProcess,
+                        BOOL bDisablePriorityBoost)
+{
+    NTSTATUS Status;
+    ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
+
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessPriorityBoost,
+                                     &PriorityBoost,
+                                     sizeof(ULONG));
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+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;
+    }
+
+    BaseSetLastNTError(Status);
+    return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+IsWow64Process(HANDLE hProcess,
+               PBOOL Wow64Process)
+{
+    ULONG_PTR pbi;
+    NTSTATUS Status;
+
+    Status = NtQueryInformationProcess(hProcess,
+                                       ProcessWow64Information,
+                                       &pbi,
+                                       sizeof(pbi),
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    *Wow64Process = (pbi != 0);
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+LPSTR
+WINAPI
+GetCommandLineA(VOID)
+{
+    DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer);
+    return CommandLineStringA.Buffer;
+}
+
+
+/*
+ * @implemented
+ */
+LPWSTR
+WINAPI
+GetCommandLineW(VOID)
+{
+    DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer);
+    return CommandLineStringW.Buffer;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+NTAPI
+ReadProcessMemory(IN HANDLE hProcess,
+                  IN LPCVOID lpBaseAddress,
+                  IN LPVOID lpBuffer,
+                  IN SIZE_T nSize,
+                  OUT SIZE_T* lpNumberOfBytesRead)
+{
+    NTSTATUS Status;
+
+    /* Do the read */
+    Status = NtReadVirtualMemory(hProcess,
+                                 (PVOID)lpBaseAddress,
+                                 lpBuffer,
+                                 nSize,
+                                 lpNumberOfBytesRead);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed */
+        BaseSetLastNTError (Status);
+        return FALSE;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+NTAPI
+WriteProcessMemory(IN HANDLE hProcess,
+                   IN LPVOID lpBaseAddress,
+                   IN LPCVOID lpBuffer,
+                   IN SIZE_T nSize,
+                   OUT SIZE_T *lpNumberOfBytesWritten)
+{
+    NTSTATUS Status;
+    ULONG OldValue;
+    SIZE_T RegionSize;
+    PVOID Base;
+    BOOLEAN UnProtect;
+
+    /* Set parameters for protect call */
+    RegionSize = nSize;
+    Base = lpBaseAddress;
+
+    /* Check the current status */
+    Status = NtProtectVirtualMemory(hProcess,
+                                    &Base,
+                                    &RegionSize,
+                                    PAGE_EXECUTE_READWRITE,
+                                    &OldValue);
+    if (NT_SUCCESS(Status))
+    {
+        /* Check if we are unprotecting */
+        UnProtect = OldValue & (PAGE_READWRITE |
+                                PAGE_WRITECOPY |
+                                PAGE_EXECUTE_READWRITE |
+                                PAGE_EXECUTE_WRITECOPY) ? FALSE : TRUE;
+        if (!UnProtect)
+        {
+            /* Set the new protection */
+            Status = NtProtectVirtualMemory(hProcess,
+                                            &Base,
+                                            &RegionSize,
+                                            OldValue,
+                                            &OldValue);
+
+            /* Write the memory */
+            Status = NtWriteVirtualMemory(hProcess,
+                                          lpBaseAddress,
+                                          (LPVOID)lpBuffer,
+                                          nSize,
+                                          lpNumberOfBytesWritten);
+            if (!NT_SUCCESS(Status))
+            {
+                /* We failed */
+                BaseSetLastNTError(Status);
+                return FALSE;
+            }
+
+            /* Flush the ITLB */
+            NtFlushInstructionCache(hProcess, lpBaseAddress, nSize);
+            return TRUE;
+        }
+        else
+        {
+            /* Check if we were read only */
+            if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY))
+            {
+                /* Restore protection and fail */
+                NtProtectVirtualMemory(hProcess,
+                                       &Base,
+                                       &RegionSize,
+                                       OldValue,
+                                       &OldValue);
+                BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
+                return FALSE;
+            }
+
+            /* Otherwise, do the write */
+            Status = NtWriteVirtualMemory(hProcess,
+                                          lpBaseAddress,
+                                          (LPVOID)lpBuffer,
+                                          nSize,
+                                          lpNumberOfBytesWritten);
+
+            /* And restore the protection */
+            NtProtectVirtualMemory(hProcess,
+                                   &Base,
+                                   &RegionSize,
+                                   OldValue,
+                                   &OldValue);
+            if (!NT_SUCCESS(Status))
+            {
+                /* We failed */
+                BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
+                return FALSE;
+            }
+
+            /* Flush the ITLB */
+            NtFlushInstructionCache(hProcess, lpBaseAddress, nSize);
+            return TRUE;
+        }
+    }
+    else
+    {
+        /* We failed */
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+ProcessIdToSessionId(IN DWORD dwProcessId,
+                     OUT DWORD *pSessionId)
+{
+    PROCESS_SESSION_INFORMATION SessionInformation;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    CLIENT_ID ClientId;
+    HANDLE ProcessHandle;
+    NTSTATUS Status;
+
+    if (IsBadWritePtr(pSessionId, sizeof(DWORD)))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    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))
+    {
+        Status = NtQueryInformationProcess(ProcessHandle,
+                                           ProcessSessionInformation,
+                                           &SessionInformation,
+                                           sizeof(SessionInformation),
+                                           NULL);
+        NtClose(ProcessHandle);
+
+        if (NT_SUCCESS(Status))
+        {
+            *pSessionId = SessionInformation.SessionId;
+            return TRUE;
+        }
+    }
+
+    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
@@ -1167,13 +2459,13 @@ GetAppName:
                 {
                     /* Fake the error */
                     CloseHandle(hFile);
-                    SetLastErrorByStatus(STATUS_OBJECT_NAME_NOT_FOUND);
+                    BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
                 }
             }
             else
             {
                 /* Immediately set the error */
-                SetLastErrorByStatus(STATUS_OBJECT_NAME_NOT_FOUND);
+                BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
             }
 
             /* Did we already fail once? */
@@ -1332,7 +2624,7 @@ GetAppName:
 
             case STATUS_OBJECT_NAME_NOT_FOUND:
             case STATUS_OBJECT_PATH_NOT_FOUND:
-                SetLastErrorByStatus(Status);
+                BaseSetLastNTError(Status);
                 goto Cleanup;
 
             default:
@@ -1361,7 +2653,7 @@ GetAppName:
     if(!NT_SUCCESS(Status))
     {
         DPRINT1("Unable to get SectionImageInformation, status 0x%x\n", Status);
-        SetLastErrorByStatus(Status);
+        BaseSetLastNTError(Status);
         goto Cleanup;
     }
 
@@ -1412,7 +2704,7 @@ GetAppName:
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Failed to connect to DbgUI!\n");
-            SetLastErrorByStatus(Status);
+            BaseSetLastNTError(Status);
             goto Cleanup;
         }
 
@@ -1438,7 +2730,7 @@ GetAppName:
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Unable to create process, status 0x%x\n", Status);
-        SetLastErrorByStatus(Status);
+        BaseSetLastNTError(Status);
         goto Cleanup;
     }
 
@@ -1452,7 +2744,7 @@ GetAppName:
         if(!NT_SUCCESS(Status))
         {
             DPRINT1("Unable to set new process priority, status 0x%x\n", Status);
-            SetLastErrorByStatus(Status);
+            BaseSetLastNTError(Status);
             goto Cleanup;
         }
     }
@@ -1595,7 +2887,7 @@ GetAppName:
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Could not initialize Process Environment\n");
-        SetLastErrorByStatus(Status);
+        BaseSetLastNTError(Status);
         goto Cleanup;
     }
 
@@ -1641,7 +2933,7 @@ GetAppName:
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("CSR Notification Failed");
-        SetLastErrorByStatus(Status);
+        BaseSetLastNTError(Status);
         goto Cleanup;
     }