Remove ps/create.c, it did not fit with the current model of abstraction. Major clean...
authorAlex Ionescu <aionescu@gmail.com>
Mon, 18 Apr 2005 02:12:30 +0000 (02:12 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 18 Apr 2005 02:12:30 +0000 (02:12 +0000)
svn path=/trunk/; revision=14662

12 files changed:
reactos/ntoskrnl/Makefile
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/ke/process.c
reactos/ntoskrnl/ps/create.c [deleted file]
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/ps/notify.c [new file with mode: 0644]
reactos/ntoskrnl/ps/process.c
reactos/ntoskrnl/ps/psmgr.c
reactos/ntoskrnl/ps/quota.c [new file with mode: 0644]
reactos/ntoskrnl/ps/suspend.c
reactos/ntoskrnl/ps/thread.c

index 3bbc692..1cfda91 100644 (file)
@@ -222,7 +222,6 @@ OBJECTS_OB = \
 # Process Manager (Ps)
 OBJECTS_PS = \
        ps/cid.o \
-       ps/create.o \
        ps/debug.o \
        ps/idle.o \
        ps/job.o \
@@ -230,6 +229,8 @@ OBJECTS_PS = \
        ps/locale.o \
        ps/process.o \
        ps/psmgr.o \
+       ps/notify.o \
+       ps/quota.o \
        ps/query.o \
        ps/security.o \
        ps/suspend.o \
index 059af38..6446c91 100644 (file)
@@ -97,6 +97,10 @@ STDCALL
 KiUnblockThread(PKTHREAD Thread, 
                 PNTSTATUS WaitStatus, 
                 KPRIORITY Increment);
+                
+NTSTATUS
+STDCALL
+KeSuspendThread(PKTHREAD Thread);
        
 /* gmutex.c ********************************************************************/
 
index 65adcd4..7c52b79 100644 (file)
@@ -533,6 +533,12 @@ PspExitThread(NTSTATUS ExitStatus);
 extern LIST_ENTRY PspReaperListHead;
 extern WORK_QUEUE_ITEM PspReaperWorkItem;
 extern BOOLEAN PspReaping;
+extern PEPROCESS PsInitialSystemProcess;
+extern PEPROCESS PsIdleProcess;
+extern POBJECT_TYPE PsProcessType;
+extern LIST_ENTRY PsActiveProcessHead;
+extern FAST_MUTEX PspActiveProcessMutex;
+extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
 
 VOID
 STDCALL
@@ -544,7 +550,7 @@ VOID PsFreezeOtherThread(PETHREAD Thread);
 VOID PsFreezeProcessThreads(PEPROCESS Process);
 VOID PsUnfreezeProcessThreads(PEPROCESS Process);
 ULONG PsEnumThreadsByProcess(PEPROCESS Process);
-PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
+PEPROCESS STDCALL PsGetNextProcess(PEPROCESS OldProcess);
 VOID
 PsApplicationProcessorInit(VOID);
 VOID
@@ -679,6 +685,9 @@ VOID PsUnlockProcess(PEPROCESS Process);
 #define EPROCESS_TO_KPROCESS(pEProcess) (&(pEProcess)->Pcb)
 #define KPROCESS_TO_EPROCESS(pKProcess) (CONTAINING_RECORD((pKProcess), EPROCESS, Pcb))
 
+#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT    8
+#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT  8
+
 #endif /* ASSEMBLER */
 
 #endif /* __INCLUDE_INTERNAL_PS_H */
index ff6f664..a03f271 100644 (file)
@@ -53,6 +53,16 @@ UpdatePageDirs(PKTHREAD Thread, PKPROCESS Process)
     MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
 }
 
+/*
+ * FUNCTION: Returns a pointer to the current process
+ */
+PKPROCESS
+STDCALL
+KeGetCurrentProcess(VOID)
+{
+    return(&(PsGetCurrentProcess()->Pcb));
+}
+
 VOID
 STDCALL
 KeInitializeProcess(PKPROCESS Process,
diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c
deleted file mode 100644 (file)
index 68f3b87..0000000
+++ /dev/null
@@ -1,642 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ps/create.c
- * PURPOSE:         Thread managment
- *
- * PROGRAMMERS:     David Welch (welch@mcmail.com)
- *                  Phillip Susi
- *                  Skywing
- */
-
-/*
- * NOTE:
- *
- * All of the routines that manipulate the thread queue synchronize on
- * a single spinlock
- *
- */
-
-/* INCLUDES ****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* GLOBAL *******************************************************************/
-
-#define MAX_THREAD_NOTIFY_ROUTINE_COUNT    8
-#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
-
-static ULONG PiThreadNotifyRoutineCount = 0;
-static PCREATE_THREAD_NOTIFY_ROUTINE
-PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
-
-ULONG
-STDCALL
-KeSuspendThread(PKTHREAD Thread);
-/* FUNCTIONS ***************************************************************/
-
-VOID
-PiBeforeBeginThread(CONTEXT c)
-{
-    KeLowerIrql(PASSIVE_LEVEL);
-}
-
-NTSTATUS
-PsInitializeThread (
-    PEPROCESS Process,
-    PETHREAD* ThreadPtr,
-    POBJECT_ATTRIBUTES ObjectAttributes,
-    KPROCESSOR_MODE AccessMode,
-    BOOLEAN First )
-{
-    PETHREAD Thread;
-    NTSTATUS Status;
-    KIRQL oldIrql;
-
-    PAGED_CODE();
-
-    if (Process == NULL)
-    {
-        Process = PsInitialSystemProcess;
-    }
-
-    /*
-    * Create and initialize thread
-    */
-    Status = ObCreateObject(AccessMode,
-        PsThreadType,
-        ObjectAttributes,
-        KernelMode,
-        NULL,
-        sizeof(ETHREAD),
-        0,
-        0,
-        (PVOID*)&Thread);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    /*
-    * Reference process
-    */
-    ObReferenceObjectByPointer(Process,
-        PROCESS_CREATE_THREAD,
-        PsProcessType,
-        KernelMode);
-
-    Thread->ThreadsProcess = Process;
-    Thread->Cid.UniqueThread = NULL;
-    Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
-
-    DPRINT("Thread = %x\n",Thread);
-
-    KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
-    InitializeListHead(&Thread->ActiveTimerListHead);
-    KeInitializeSpinLock(&Thread->ActiveTimerListLock);
-    InitializeListHead(&Thread->IrpList);
-    Thread->DeadThread = FALSE;
-    Thread->HasTerminated = FALSE;
-    Thread->Tcb.Win32Thread = NULL;
-    DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
-
-
-    Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority;
-    Thread->Tcb.Priority = Thread->Tcb.BasePriority;
-
-    /*
-    * Local Procedure Call facility (LPC)
-    */
-    KeInitializeSemaphore  (& Thread->LpcReplySemaphore, 0, LONG_MAX);
-    Thread->LpcReplyMessage = NULL;
-    Thread->LpcReplyMessageId = 0; /* not valid */
-    /* Thread->LpcReceiveMessageId = 0; */
-    Thread->LpcExitThreadCalled = FALSE;
-    Thread->LpcReceivedMsgIdValid = FALSE;
-
-    oldIrql = KeAcquireDispatcherDatabaseLock();
-    InsertTailList(&Process->ThreadListHead,
-        &Thread->ThreadListEntry);
-    KeReleaseDispatcherDatabaseLock(oldIrql);
-
-    *ThreadPtr = Thread;
-
-    return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-PsCreateTeb (
-    HANDLE ProcessHandle,
-    PTEB *TebPtr,
-    PETHREAD Thread,
-    PINITIAL_TEB InitialTeb )
-{
-    PEPROCESS Process;
-    NTSTATUS Status;
-    ULONG ByteCount;
-    ULONG RegionSize;
-    ULONG TebSize;
-    PVOID TebBase;
-    TEB Teb;
-
-    PAGED_CODE();
-
-    TebSize = PAGE_SIZE;
-
-    if (NULL == Thread->ThreadsProcess)
-    {
-    /* We'll be allocating a 64k block here and only use 4k of it, but this
-    path should almost never be taken. Actually, I never saw it was taken,
-    so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and
-        move on */
-        TebBase = NULL;
-        Status = ZwAllocateVirtualMemory(ProcessHandle,
-            &TebBase,
-            0,
-            &TebSize,
-            MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
-            PAGE_READWRITE);
-        if (! NT_SUCCESS(Status))
-        {
-            DPRINT1("Failed to allocate virtual memory for TEB\n");
-            return Status;
-        }
-    }
-    else
-    {
-        Process = Thread->ThreadsProcess;
-        PsLockProcess(Process, FALSE);
-        if (NULL == Process->TebBlock ||
-            Process->TebBlock == Process->TebLastAllocated)
-        {
-            Process->TebBlock = NULL;
-            RegionSize = MM_VIRTMEM_GRANULARITY;
-            Status = ZwAllocateVirtualMemory(ProcessHandle,
-                &Process->TebBlock,
-                0,
-                &RegionSize,
-                MEM_RESERVE | MEM_TOP_DOWN,
-                PAGE_READWRITE);
-            if (! NT_SUCCESS(Status))
-            {
-                PsUnlockProcess(Process);
-                DPRINT1("Failed to reserve virtual memory for TEB\n");
-                return Status;
-            }
-            Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize);
-        }
-        TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE);
-        Status = ZwAllocateVirtualMemory(ProcessHandle,
-            &TebBase,
-            0,
-            &TebSize,
-            MEM_COMMIT,
-            PAGE_READWRITE);
-        if (! NT_SUCCESS(Status))
-        {
-            DPRINT1("Failed to commit virtual memory for TEB\n");
-            return Status;
-        }
-        Process->TebLastAllocated = TebBase;
-        PsUnlockProcess(Process);
-    }
-
-    DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
-    ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize);
-
-    RtlZeroMemory(&Teb, sizeof(TEB));
-    /* set all pointers to and from the TEB */
-    Teb.Tib.Self = TebBase;
-    if (Thread->ThreadsProcess)
-    {
-        Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
-    }
-    DPRINT("Teb.Peb %x\n", Teb.Peb);
-
-    /* store stack information from InitialTeb */
-    if(InitialTeb != NULL)
-    {
-        /* fixed-size stack */
-        if(InitialTeb->StackBase && InitialTeb->StackLimit)
-        {
-            Teb.Tib.StackBase = InitialTeb->StackBase;
-            Teb.Tib.StackLimit = InitialTeb->StackLimit;
-            Teb.DeallocationStack = InitialTeb->StackLimit;
-        }
-        /* expandable stack */
-        else
-        {
-            Teb.Tib.StackBase = InitialTeb->StackCommit;
-            Teb.Tib.StackLimit = InitialTeb->StackCommitMax;
-            Teb.DeallocationStack = InitialTeb->StackReserved;
-        }
-    }
-
-    /* more initialization */
-    Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
-    Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
-    Teb.CurrentLocale = PsDefaultThreadLocaleId;
-
-    /* Terminate the exception handler list */
-    Teb.Tib.ExceptionList = (PVOID)-1;
-
-    DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
-
-    /* write TEB data into teb page */
-    Status = NtWriteVirtualMemory(ProcessHandle,
-        TebBase,
-        &Teb,
-        sizeof(TEB),
-        &ByteCount);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* free TEB */
-        DPRINT1 ("Writing TEB failed!\n");
-
-        RegionSize = 0;
-        NtFreeVirtualMemory(ProcessHandle,
-            TebBase,
-            &RegionSize,
-            MEM_RELEASE);
-
-        return Status;
-    }
-
-    if (TebPtr != NULL)
-    {
-        *TebPtr = (PTEB)TebBase;
-    }
-
-    DPRINT("TEB allocated at %p\n", TebBase);
-
-    return Status;
-}
-
-
-VOID STDCALL
-LdrInitApcRundownRoutine ( PKAPC Apc )
-{
-    ExFreePool(Apc);
-}
-
-
-VOID STDCALL
-LdrInitApcKernelRoutine (
-    PKAPC Apc,
-    PKNORMAL_ROUTINE* NormalRoutine,
-    PVOID* NormalContext,
-    PVOID* SystemArgument1,
-    PVOID* SystemArgument2)
-{
-    ExFreePool(Apc);
-}
-
-
-NTSTATUS STDCALL
-NtCreateThread (
-    OUT PHANDLE ThreadHandle,
-    IN ACCESS_MASK DesiredAccess,
-    IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-    IN HANDLE ProcessHandle,
-    OUT PCLIENT_ID ClientId,
-    IN PCONTEXT ThreadContext,
-    IN PINITIAL_TEB InitialTeb,
-    IN BOOLEAN CreateSuspended )
-{
-    HANDLE hThread;
-    CONTEXT SafeContext;
-    INITIAL_TEB SafeInitialTeb;
-    PEPROCESS Process;
-    PETHREAD Thread;
-    PTEB TebBase;
-    PKAPC LdrInitApc;
-    KIRQL oldIrql;
-    KPROCESSOR_MODE PreviousMode;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    PAGED_CODE();
-
-    if(ThreadContext == NULL)
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    PreviousMode = ExGetPreviousMode();
-
-    if(PreviousMode != KernelMode)
-    {
-        _SEH_TRY
-        {
-            ProbeForWrite(ThreadHandle,
-                sizeof(HANDLE),
-                sizeof(ULONG));
-            if(ClientId != NULL)
-            {
-                ProbeForWrite(ClientId,
-                    sizeof(CLIENT_ID),
-                    sizeof(ULONG));
-            }
-            ProbeForRead(ThreadContext,
-                sizeof(CONTEXT),
-                sizeof(ULONG));
-            SafeContext = *ThreadContext;
-            ThreadContext = &SafeContext;
-            ProbeForRead(InitialTeb,
-                sizeof(INITIAL_TEB),
-                sizeof(ULONG));
-            SafeInitialTeb = *InitialTeb;
-            InitialTeb = &SafeInitialTeb;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if(!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
-    }
-
-    DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
-        ThreadHandle,ThreadContext);
-
-    Status = ObReferenceObjectByHandle(
-        ProcessHandle,
-        PROCESS_CREATE_THREAD,
-        PsProcessType,
-        PreviousMode,
-        (PVOID*)&Process,
-        NULL);
-    if(!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    Status = PsLockProcess(Process, FALSE);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(Process);
-        return(Status);
-    }
-
-    if(Process->ExitTime.QuadPart != 0)
-    {
-        PsUnlockProcess(Process);
-        return STATUS_PROCESS_IS_TERMINATING;
-    }
-
-    PsUnlockProcess(Process);
-
-    Status = PsInitializeThread(Process,
-        &Thread,
-        ObjectAttributes,
-        PreviousMode,
-        FALSE);
-
-    ObDereferenceObject(Process);
-
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    /* create a client id handle */
-    Status = PsCreateCidHandle (
-        Thread, PsThreadType, &Thread->Cid.UniqueThread);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(Thread);
-        return Status;
-    }
-
-    Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
-    if (!NT_SUCCESS(Status))
-    {
-        PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
-        ObDereferenceObject(Thread);
-        return(Status);
-    }
-
-    Status = PsCreateTeb(ProcessHandle,
-        &TebBase,
-        Thread,
-        InitialTeb);
-    if (!NT_SUCCESS(Status))
-    {
-        PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
-        ObDereferenceObject(Thread);
-        return(Status);
-    }
-    Thread->Tcb.Teb = TebBase;
-
-    Thread->StartAddress = NULL;
-
-    /*
-    * Maybe send a message to the process's debugger
-    */
-    DbgkCreateThread((PVOID)ThreadContext->Eip);
-
-    /*
-    * First, force the thread to be non-alertable for user-mode alerts.
-    */
-    Thread->Tcb.Alertable = FALSE;
-
-    /*
-    * If the thread is to be created suspended then queue an APC to
-    * do the suspend before we run any userspace code.
-    */
-    if (CreateSuspended)
-    {
-        KeSuspendThread(&Thread->Tcb);
-    }
-
-    /*
-    * Queue an APC to the thread that will execute the ntdll startup
-    * routine.
-    */
-    LdrInitApc = ExAllocatePoolWithTag (
-        NonPagedPool, sizeof(KAPC), TAG_KAPC );
-    KeInitializeApc (
-        LdrInitApc,
-        &Thread->Tcb,
-        OriginalApcEnvironment,
-        LdrInitApcKernelRoutine,
-        LdrInitApcRundownRoutine,
-        LdrpGetSystemDllEntryPoint(),
-        UserMode,
-        NULL );
-    KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT);
-    /*
-    * The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE.
-    * We must do this manually. Do NOT attempt to set the Thread to Alertable before the call,
-    * doing so is a blatant and erronous hack.
-    */
-    Thread->Tcb.ApcState.UserApcPending = TRUE;
-    Thread->Tcb.Alerted[KernelMode] = TRUE;
-
-    oldIrql = KeAcquireDispatcherDatabaseLock ();
-    KiUnblockThread(&Thread->Tcb, NULL, 0);
-    KeReleaseDispatcherDatabaseLock(oldIrql);
-
-    Status = ObInsertObject((PVOID)Thread,
-        NULL,
-        DesiredAccess,
-        0,
-        NULL,
-        &hThread);
-    if(NT_SUCCESS(Status))
-    {
-        _SEH_TRY
-        {
-            if(ClientId != NULL)
-            {
-                *ClientId = Thread->Cid;
-            }
-            *ThreadHandle = hThread;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-    }
-
-    return Status;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-PsCreateSystemThread (
-    PHANDLE ThreadHandle,
-    ACCESS_MASK DesiredAccess,
-    POBJECT_ATTRIBUTES ObjectAttributes,
-    HANDLE ProcessHandle,
-    PCLIENT_ID ClientId,
-    PKSTART_ROUTINE StartRoutine,
-    PVOID StartContext )
-/*
- * FUNCTION: Creates a thread which executes in kernel mode
- * ARGUMENTS:
- *       ThreadHandle (OUT) = Caller supplied storage for the returned thread
- *                            handle
- *       DesiredAccess = Requested access to the thread
- *       ObjectAttributes = Object attributes (optional)
- *       ProcessHandle = Handle of process thread will run in
- *                       NULL to use system process
- *       ClientId (OUT) = Caller supplied storage for the returned client id
- *                        of the thread (optional)
- *       StartRoutine = Entry point for the thread
- *       StartContext = Argument supplied to the thread when it begins
- *                     execution
- * RETURNS: Success or failure status
- */
-{
-    PETHREAD Thread;
-    NTSTATUS Status;
-    KIRQL oldIrql;
-
-    PAGED_CODE();
-
-    DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
-        ThreadHandle,ProcessHandle);
-
-    Status = PsInitializeThread(
-        NULL,
-        &Thread,
-        ObjectAttributes,
-        KernelMode,
-        FALSE);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    /* Set the thread as a system thread */
-    Thread->SystemThread = TRUE;
-
-    Status = PsCreateCidHandle(Thread,
-        PsThreadType,
-        &Thread->Cid.UniqueThread);
-    if(!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(Thread);
-        return Status;
-    }
-
-    Thread->StartAddress = StartRoutine;
-    Status = KiArchInitThread (
-        &Thread->Tcb, StartRoutine, StartContext);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(Thread);
-        return(Status);
-    }
-
-    if (ClientId != NULL)
-    {
-        *ClientId=Thread->Cid;
-    }
-
-    oldIrql = KeAcquireDispatcherDatabaseLock ();
-    KiUnblockThread(&Thread->Tcb, NULL, 0);
-    KeReleaseDispatcherDatabaseLock(oldIrql);
-
-    Status = ObInsertObject(
-        (PVOID)Thread,
-        NULL,
-        DesiredAccess,
-        0,
-        NULL,
-        ThreadHandle);
-
-    /* don't dereference the thread, the initial reference serves as the keep-alive
-    reference which will be removed by the thread reaper */
-
-    return Status;
-}
-
-
-VOID STDCALL
-PspRunCreateThreadNotifyRoutines (
-    PETHREAD CurrentThread,
-    BOOLEAN Create )
-{
-    ULONG i;
-    CLIENT_ID Cid = CurrentThread->Cid;
-
-    for (i = 0; i < PiThreadNotifyRoutineCount; i++)
-    {
-        PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
-    }
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-PsSetCreateThreadNotifyRoutine (
-    IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
-{
-    if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
-    {
-        return(STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-    PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
-    PiThreadNotifyRoutineCount++;
-
-    return(STATUS_SUCCESS);
-}
-
-/* EOF */
index cda7b57..37b1c40 100644 (file)
@@ -79,6 +79,35 @@ PspReapRoutine(PVOID Context)
     KeReleaseDispatcherDatabaseLock(OldIrql);
 }
 
+VOID
+STDCALL
+PspKillMostProcesses(VOID)
+{
+    PLIST_ENTRY current_entry;
+    PEPROCESS current;
+   
+    /* Acquire the Active Process Lock */
+    ExAcquireFastMutex(&PspActiveProcessMutex);   
+    
+    /* Loop all processes on the list */
+    current_entry = PsActiveProcessHead.Flink;
+    while (current_entry != &PsActiveProcessHead)
+    {
+        current = CONTAINING_RECORD(current_entry, EPROCESS, ProcessListEntry);
+        current_entry = current_entry->Flink;
+    
+        if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
+            current->UniqueProcessId != PsGetCurrentProcessId())
+        {
+            /* Terminate all the Threads in this Process */
+            PspTerminateProcessThreads(current, STATUS_SUCCESS);
+        }
+    }
+   
+    /* Release the lock */
+    ExReleaseFastMutex(&PspActiveProcessMutex);
+}
+
 VOID
 STDCALL
 PspTerminateProcessThreads(PEPROCESS Process,
diff --git a/reactos/ntoskrnl/ps/notify.c b/reactos/ntoskrnl/ps/notify.c
new file mode 100644 (file)
index 0000000..2bccc23
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/notify.c
+ * PURPOSE:         Notifications
+ *
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* GLOBAL *******************************************************************/
+
+#define MAX_THREAD_NOTIFY_ROUTINE_COUNT    8
+#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
+
+static ULONG PiThreadNotifyRoutineCount = 0;
+static PCREATE_THREAD_NOTIFY_ROUTINE
+PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
+
+static PCREATE_PROCESS_NOTIFY_ROUTINE 
+PspProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
+
+static PLOAD_IMAGE_NOTIFY_ROUTINE
+PspLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
+
+/* FUNCTIONS ***************************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
+                                IN BOOLEAN Remove)
+{
+    ULONG i;
+
+    /* Check if it's a removal or addition */
+    if (Remove)
+    {
+        /* Loop the routines */
+        for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
+        {
+            /* Check for a match */
+            if ((PVOID)PspProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
+            {
+                /* Remove and return */
+                PspProcessNotifyRoutine[i] = NULL;
+                return(STATUS_SUCCESS);
+            }
+        }
+    } 
+    else 
+    {
+        /* Loop the routines */
+        for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
+        {
+            /* Find an empty one */
+            if (PspProcessNotifyRoutine[i] == NULL)
+            {
+                /* Add it */
+                PspProcessNotifyRoutine[i] = NotifyRoutine;
+                return STATUS_SUCCESS;
+            }
+        }
+    }
+    
+    /* Nothing found */
+    return STATUS_INVALID_PARAMETER;
+}
+
+/*
+ * @implemented
+ */                       
+NTSTATUS
+STDCALL
+PsRemoveLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
+{
+    ULONG i;
+    
+    /* Loop the routines */
+    for(i=0;i<MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT;i++)
+    {
+        /* Check for a match */
+        if ((PVOID)PspLoadImageNotifyRoutine[i] == (PVOID)NotifyRoutine)
+        {
+            /* Remove and return */
+            PspLoadImageNotifyRoutine[i] = NULL;
+            return(STATUS_SUCCESS);
+        }
+    }
+    
+    /* Nothing found */
+    return STATUS_INVALID_PARAMETER;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
+{
+    ULONG i;
+
+    /* Loop the routines */
+    for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
+    {
+        /* Find an empty one */
+        if (PspLoadImageNotifyRoutine[i] == NULL)
+        {
+            /* Add it */
+            PspLoadImageNotifyRoutine[i] = NotifyRoutine;
+            return STATUS_SUCCESS;
+        }
+    }
+
+    /* Nothing found */
+    return STATUS_INVALID_PARAMETER;
+}
+
+VOID STDCALL
+PspRunCreateThreadNotifyRoutines (
+    PETHREAD CurrentThread,
+    BOOLEAN Create )
+{
+    ULONG i;
+    CLIENT_ID Cid = CurrentThread->Cid;
+
+    for (i = 0; i < PiThreadNotifyRoutineCount; i++)
+    {
+        PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
+    }
+}
+
+VOID
+STDCALL
+PspRunCreateProcessNotifyRoutines(PEPROCESS CurrentProcess,
+                                  BOOLEAN Create)
+{
+    ULONG i;
+    HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
+    HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
+    for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++i) 
+    {
+        if(PspProcessNotifyRoutine[i]) 
+        {
+            PspProcessNotifyRoutine[i](ParentId, ProcessId, Create);
+        }
+    }
+}
+
+VOID 
+STDCALL
+PspRunLoadImageNotifyRoutines(PUNICODE_STRING FullImageName,
+                              HANDLE ProcessId,
+                              PIMAGE_INFO ImageInfo)
+{
+    ULONG i;
+    for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
+    {
+        if (PspLoadImageNotifyRoutine[i])
+        {
+            PspLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
+        }
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsSetCreateThreadNotifyRoutine (
+    IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
+{
+    if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
+    {
+        return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+    PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
+    PiThreadNotifyRoutineCount++;
+
+    return(STATUS_SUCCESS);
+}
+
+/* EOF */
index 2a1c42c..e12a8e8 100644 (file)
@@ -1,11 +1,11 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ps/process.c
  * PURPOSE:         Process managment
  *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES ******************************************************************/
 
 /* GLOBALS ******************************************************************/
 
-VOID INIT_FUNCTION PsInitClientIDManagment(VOID);
-
 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
 PEPROCESS PsIdleProcess = NULL;
-
 POBJECT_TYPE EXPORTED PsProcessType = NULL;
 
 LIST_ENTRY PsActiveProcessHead;
 FAST_MUTEX PspActiveProcessMutex;
-static LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
-
-static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
-                                          STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
-                       PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
-                       PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
-                                          STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
-                                          PROCESS_ALL_ACCESS};
-
-#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT    8
-#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT  8
-
-static PCREATE_PROCESS_NOTIFY_ROUTINE
-PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
-static PLOAD_IMAGE_NOTIFY_ROUTINE
-PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
+LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
                              
-/* FUNCTIONS *****************************************************************/
-
-PEPROCESS
-PsGetNextProcess(PEPROCESS OldProcess)
-{
-   PEPROCESS NextProcess;
-   NTSTATUS Status;
-   
-   if (OldProcess == NULL)
-     {
-       Status = ObReferenceObjectByPointer(PsIdleProcess,
-                                          PROCESS_ALL_ACCESS,
-                                          PsProcessType,
-                                          KernelMode);   
-       if (!NT_SUCCESS(Status))
-         {
-          CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
-          KEBUGCHECK(0);
-        }
-       return PsIdleProcess;
-     }
-   
-   ExAcquireFastMutex(&PspActiveProcessMutex);
-   NextProcess = OldProcess;
-   while (1)
-     {
-       PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
-                                                           NextProcess->ProcessListEntry.Flink);
-       if (Flink != &PsActiveProcessHead)
-         {
-           NextProcess = CONTAINING_RECORD(Flink,
-                                          EPROCESS,
-                                          ProcessListEntry);
-         }
-       else
-         {
-           NextProcess = NULL;
-           break;
-         }
+/* INTERNAL FUNCTIONS *****************************************************************/
 
-       Status = ObReferenceObjectByPointer(NextProcess,
-                                          PROCESS_ALL_ACCESS,
-                                          PsProcessType,
-                                          KernelMode);   
-       if (NT_SUCCESS(Status))
-         {
-          break;
-        }
-       else if (Status == STATUS_PROCESS_IS_TERMINATING)
-         {
-          continue;
-        }
-       else if (!NT_SUCCESS(Status))
-         {
-          continue;
-        }
-     }
-
-   ExReleaseFastMutex(&PspActiveProcessMutex);
-   ObDereferenceObject(OldProcess);
-   
-   return(NextProcess);
-}
-
-VOID 
-PiKillMostProcesses(VOID)
-{
-   PLIST_ENTRY current_entry;
-   PEPROCESS current;
-   
-   ExAcquireFastMutex(&PspActiveProcessMutex);   
-   current_entry = PsActiveProcessHead.Flink;
-   while (current_entry != &PsActiveProcessHead)
-     {
-       current = CONTAINING_RECORD(current_entry, EPROCESS, 
-                                   ProcessListEntry);
-       current_entry = current_entry->Flink;
-       
-       if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
-           current->UniqueProcessId != PsGetCurrentProcessId())
-         {
-            PspTerminateProcessThreads(current, STATUS_SUCCESS);
-         }
-     }
-   
-   ExReleaseFastMutex(&PspActiveProcessMutex);
-}
-
-VOID INIT_FUNCTION
-PsInitProcessManagment(VOID)
+NTSTATUS
+PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
 {
-   PKPROCESS KProcess;
-   NTSTATUS Status;
-   
-   ShortPsLockDelay.QuadPart = -100LL;
-   PsLockTimeout.QuadPart = -10000000LL; /* one second */
-   /*
-    * Register the process object type
-    */
-   
-   PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
-
-   PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
-   PsProcessType->TotalObjects = 0;
-   PsProcessType->TotalHandles = 0;
-   PsProcessType->PeakObjects = 0;
-   PsProcessType->PeakHandles = 0;
-   PsProcessType->PagedPoolCharge = 0;
-   PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
-   PsProcessType->Mapping = &PiProcessMapping;
-   PsProcessType->Dump = NULL;
-   PsProcessType->Open = NULL;
-   PsProcessType->Close = NULL;
-   PsProcessType->Delete = PspDeleteProcess;
-   PsProcessType->Parse = NULL;
-   PsProcessType->Security = NULL;
-   PsProcessType->QueryName = NULL;
-   PsProcessType->OkayToClose = NULL;
-   PsProcessType->Create = NULL;
-   PsProcessType->DuplicationNotify = NULL;
-   
-   RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
-   
-   ObpCreateTypeObject(PsProcessType);
-
-   InitializeListHead(&PsActiveProcessHead);
-   ExInitializeFastMutex(&PspActiveProcessMutex);
-
-   RtlZeroMemory(PiProcessNotifyRoutine, sizeof(PiProcessNotifyRoutine));
-   RtlZeroMemory(PiLoadImageNotifyRoutine, sizeof(PiLoadImageNotifyRoutine));
-   
-   /*
-    * Initialize the idle process
-    */
-   Status = ObCreateObject(KernelMode,
-                          PsProcessType,
-                          NULL,
-                          KernelMode,
-                          NULL,
-                          sizeof(EPROCESS),
-                          0,
-                          0,
-                          (PVOID*)&PsIdleProcess);
-   if (!NT_SUCCESS(Status))
-     {
-        DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status);
-        KEBUGCHECK(0);
-        return;
-     }
-
-   RtlZeroMemory(PsIdleProcess, sizeof(EPROCESS));
-   
-   PsIdleProcess->Pcb.Affinity = 0xFFFFFFFF;
-   PsIdleProcess->Pcb.IopmOffset = 0xffff;
-   PsIdleProcess->Pcb.LdtDescriptor[0] = 0;
-   PsIdleProcess->Pcb.LdtDescriptor[1] = 0;
-   PsIdleProcess->Pcb.BasePriority = PROCESS_PRIO_IDLE;
-   PsIdleProcess->Pcb.ThreadQuantum = 6;
-   InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
-   InitializeListHead(&PsIdleProcess->ThreadListHead);
-   InitializeListHead(&PsIdleProcess->ProcessListEntry);
-   KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.DispatcherHeader,
-                               ProcessObject,
-                               sizeof(EPROCESS),
-                               FALSE);
-   PsIdleProcess->Pcb.DirectoryTableBase =
-     (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
-   strcpy(PsIdleProcess->ImageFileName, "Idle");
-
-   /*
-    * Initialize the system process
-    */
-   Status = ObCreateObject(KernelMode,
-                          PsProcessType,
-                          NULL,
-                          KernelMode,
-                          NULL,
-                          sizeof(EPROCESS),
-                          0,
-                          0,
-                          (PVOID*)&PsInitialSystemProcess);
-   if (!NT_SUCCESS(Status))
-     {
-        DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status);
-        KEBUGCHECK(0);
-        return;
-     }
-   
-   /* System threads may run on any processor. */
-   PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
-   PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
-   PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
-   PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
-   PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
-   PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
-   InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
-   KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
-                               ProcessObject,
-                               sizeof(EPROCESS),
-                               FALSE);
-   KProcess = &PsInitialSystemProcess->Pcb;
-   
-   MmInitializeAddressSpace(PsInitialSystemProcess,
-                           &PsInitialSystemProcess->AddressSpace);
-   
-   KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
-   PsInitialSystemProcess->LockCount = 0;
-   PsInitialSystemProcess->LockOwner = NULL;
-
-#if defined(__GNUC__)
-   KProcess->DirectoryTableBase = 
-     (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
-#else
-   {
-     LARGE_INTEGER dummy;
-     dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
-     KProcess->DirectoryTableBase = dummy;
-   }
-#endif
+  ULONG Attempts = 0;
+  PKTHREAD PrevLockOwner;
+  NTSTATUS Status = STATUS_UNSUCCESSFUL;
+  PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
+  PKTHREAD CallingThread = KeGetCurrentThread();
+  
+  PAGED_CODE();
+  
+  KeEnterCriticalRegion();
+  
+  for(;;)
+  {
+    PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
+      &Process->LockOwner, CallingThread, NULL);
+    if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
+    {
+      /* we got the lock or already locked it */
+      if(InterlockedIncrementUL(&Process->LockCount) == 1)
+      {
+        KeClearEvent(&Process->LockEvent);
+      }
 
-   strcpy(PsInitialSystemProcess->ImageFileName, "System");
-   
-   PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
-   
-   InsertHeadList(&PsActiveProcessHead,
-                 &PsInitialSystemProcess->ProcessListEntry);
-   InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
-   
-#ifndef SCHED_REWRITE
-    PTOKEN BootToken;
-        
-    /* No parent, this is the Initial System Process. Assign Boot Token */
-    BootToken = SepCreateSystemProcessToken();
-    BootToken->TokenInUse = TRUE;
-    PsInitialSystemProcess->Token = BootToken;
-    ObReferenceObject(BootToken);
+      return STATUS_SUCCESS;
+    }
+    else
+    {
+      if(++Attempts > 2)
+      {
+        Status = KeWaitForSingleObject(&Process->LockEvent,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       Delay);
+        if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
+        {
+#ifndef NDEBUG
+          if(Status == STATUS_TIMEOUT)
+          {
+            DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
+          }
 #endif
+          KeLeaveCriticalRegion();
+          break;
+        }
+      }
+      else
+      {
+        KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
+      }
+    }
+  }
+  
+  return Status;
 }
 
 VOID
-PspPostInitSystemProcess(VOID)
+PsUnlockProcess(PEPROCESS Process)
 {
-  NTSTATUS Status;
-  
-  /* this routine is called directly after the exectuive handle tables were
-     initialized. We'll set up the Client ID handle table and assign the system
-     process a PID */
-  PsInitClientIDManagment();
+  PAGED_CODE();
   
-  ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess);
-  ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable;
+  ASSERT(Process->LockOwner == KeGetCurrentThread());
   
-  Status = PsCreateCidHandle(PsInitialSystemProcess,
-                             PsProcessType,
-                             &PsInitialSystemProcess->UniqueProcessId);
-  if(!NT_SUCCESS(Status))
+  if(InterlockedDecrementUL(&Process->LockCount) == 0)
   {
-    DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
-    KEBUGCHECK(0);
+    InterlockedExchangePointer(&Process->LockOwner, NULL);
+    KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
   }
+  
+  KeLeaveCriticalRegion();
 }
 
-PKPROCESS
-KeGetCurrentProcess(VOID)
-/*
- * FUNCTION: Returns a pointer to the current process
- */
-{
-  return(&(PsGetCurrentProcess()->Pcb));
-}
-
-/*
- * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
- * ULONG ProcessId! (Skywing)
- */
-/*
- * @implemented
- */
-HANDLE STDCALL
-PsGetCurrentProcessId(VOID)
-{
-  return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
-}
-
-/*
- * @unimplemented
- */
-ULONG
+PEPROCESS
 STDCALL
-PsGetCurrentProcessSessionId (
-       VOID
-       )
+PsGetNextProcess(PEPROCESS OldProcess)
 {
-       return PsGetCurrentProcess()->SessionId;
-}
+    PEPROCESS NextProcess;
+    NTSTATUS Status;
+   
+    /* Check if we have a previous process */
+    if (OldProcess == NULL)
+    {
+        /* We don't, start with the Idle Process */
+        Status = ObReferenceObjectByPointer(PsIdleProcess,
+                                            PROCESS_ALL_ACCESS,
+                                            PsProcessType,
+                                            KernelMode);   
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
+            KEBUGCHECK(0);
+        }
+        
+        return PsIdleProcess;
+    }
+   
+    /* Acquire the Active Process Lock */
+    ExAcquireFastMutex(&PspActiveProcessMutex);
+    
+    /* Start at the previous process */
+    NextProcess = OldProcess;
+    
+    /* Loop until we fail */
+    while (1)
+    {
+        /* Get the Process Link */
+        PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
+                             NextProcess->ProcessListEntry.Flink);
+        
+        /* Move to the next Process if we're not back at the beginning */
+        if (Flink != &PsActiveProcessHead)
+        {
+            NextProcess = CONTAINING_RECORD(Flink, EPROCESS, ProcessListEntry);
+        }
+        else
+        {
+            NextProcess = NULL;
+            break;
+        }
 
-/*
- * FUNCTION: Returns a pointer to the current process
- *
- * @implemented
- */
-PEPROCESS STDCALL
-IoGetCurrentProcess(VOID)
-{
-   if (PsGetCurrentThread() == NULL || 
-       PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
-     {
-       return(PsInitialSystemProcess);
-     }
-   else
-     {
-       return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
-     }
+        /* Reference the Process */
+        Status = ObReferenceObjectByPointer(NextProcess,
+                                            PROCESS_ALL_ACCESS,
+                                            PsProcessType,
+                                            KernelMode);
+
+        /* Exit the loop if the reference worked, keep going if there's an error */               
+        if (NT_SUCCESS(Status)) break;
+    }
+    
+    /* Release the lock */
+    ExReleaseFastMutex(&PspActiveProcessMutex);
+    
+    /* Reference the Process we had referenced earlier */
+    ObDereferenceObject(OldProcess);
+    return(NextProcess);
 }
 
 NTSTATUS
@@ -630,198 +439,72 @@ exitdereferenceobjects:
     return Status;
 }
 
+/* PUBLIC FUNCTIONS *****************************************************************/
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS 
+STDCALL
 PsCreateSystemProcess(PHANDLE ProcessHandle,
-                     ACCESS_MASK DesiredAccess,
-                     POBJECT_ATTRIBUTES ObjectAttributes)
+                      ACCESS_MASK DesiredAccess,
+                      POBJECT_ATTRIBUTES ObjectAttributes)
 {
-   return PspCreateProcess(ProcessHandle,
-                          DesiredAccess,
-                          ObjectAttributes,
-                          NULL, /* no parent process */
-                          FALSE,
-                          NULL,
-                          NULL,
-                          NULL);
+    return PspCreateProcess(ProcessHandle,
+                            DesiredAccess,
+                            ObjectAttributes,
+                            NULL, /* no parent process */
+                            FALSE,
+                            NULL,
+                            NULL,
+                            NULL);
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-NtCreateProcess(OUT PHANDLE ProcessHandle,
-               IN ACCESS_MASK DesiredAccess,
-               IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-               IN HANDLE ParentProcess,
-               IN BOOLEAN InheritObjectTable,
-               IN HANDLE SectionHandle  OPTIONAL,
-               IN HANDLE DebugPort  OPTIONAL,
-               IN HANDLE ExceptionPort  OPTIONAL)
-/*
- * FUNCTION: Creates a process.
- * ARGUMENTS:
- *        ProcessHandle (OUT) = Caller supplied storage for the resulting
- *                              handle
- *        DesiredAccess = Specifies the allowed or desired access to the
- *                        process can be a combination of
- *                        STANDARD_RIGHTS_REQUIRED| ..
- *        ObjectAttribute = Initialized attributes for the object, contains
- *                          the rootdirectory and the filename
- *        ParentProcess = Handle to the parent process.
- *        InheritObjectTable = Specifies to inherit the objects of the parent
- *                             process if true.
- *        SectionHandle = Handle to a section object to back the image file
- *        DebugPort = Handle to a DebugPort if NULL the system default debug
- *                    port will be used.
- *        ExceptionPort = Handle to a exception port.
- * REMARKS:
- *        This function maps to the win32 CreateProcess.
- * RETURNS: Status
- */
+NTSTATUS 
+STDCALL
+PsLookupProcessByProcessId(IN HANDLE ProcessId,
+                           OUT PEPROCESS *Process)
 {
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
+   PHANDLE_TABLE_ENTRY CidEntry;
+   PEPROCESS FoundProcess;
+
    PAGED_CODE();
-  
-   PreviousMode = ExGetPreviousMode();
-   
-   if(PreviousMode != KernelMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForWrite(ProcessHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
 
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
-   
-   if(ParentProcess == NULL)
-   {
-     Status = STATUS_INVALID_PARAMETER;
-   }
-   else
+   ASSERT(Process);
+
+   CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
+   if(CidEntry != NULL)
    {
-     Status = PspCreateProcess(ProcessHandle,
-                               DesiredAccess,
-                               ObjectAttributes,
-                               ParentProcess,
-                               InheritObjectTable,
-                               SectionHandle,
-                               DebugPort,
-                               ExceptionPort);
-   }
-   
-   return Status;
-}
+       ObReferenceObject(FoundProcess);
 
+        PsUnlockCidHandle(CidEntry);
+
+        *Process = FoundProcess;
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_INVALID_PARAMETER;
+}
 
 /*
- * @unimplemented
+ * FUNCTION: Returns a pointer to the current process
+ *
+ * @implemented
  */
-NTSTATUS STDCALL
-NtOpenProcess(OUT PHANDLE          ProcessHandle,
-             IN  ACCESS_MASK       DesiredAccess,
-             IN  POBJECT_ATTRIBUTES  ObjectAttributes,
-             IN  PCLIENT_ID        ClientId)
+PEPROCESS STDCALL
+IoGetCurrentProcess(VOID)
 {
-   DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
-         "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
-         ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
-         ClientId->UniqueProcess, ClientId->UniqueThread);
-
-   PAGED_CODE();
-   
-   /*
-    * Not sure of the exact semantics 
-    */
-   if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
-       ObjectAttributes->ObjectName->Buffer != NULL)
+   if (PsGetCurrentThread() == NULL || 
+       PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
      {
-       NTSTATUS Status;
-       PEPROCESS Process;
-               
-       Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
-                                        ObjectAttributes->Attributes,
-                                        NULL,
-                                        DesiredAccess,
-                                        PsProcessType,
-                                        UserMode,
-                                        NULL,
-                                        (PVOID*)&Process);
-       if (Status != STATUS_SUCCESS)
-         {
-            return(Status);
-         }
-       
-       Status = ObCreateHandle(PsGetCurrentProcess(),
-                               Process,
-                               DesiredAccess,
-                               FALSE,
-                               ProcessHandle);
-       ObDereferenceObject(Process);
-   
-       return(Status);
+       return(PsInitialSystemProcess);
      }
    else
      {
-       PLIST_ENTRY current_entry;
-       PEPROCESS current;
-       NTSTATUS Status;
-       
-       ExAcquireFastMutex(&PspActiveProcessMutex);
-       current_entry = PsActiveProcessHead.Flink;
-       while (current_entry != &PsActiveProcessHead)
-         {
-            current = CONTAINING_RECORD(current_entry, EPROCESS, 
-                                        ProcessListEntry);
-            if (current->UniqueProcessId == ClientId->UniqueProcess)
-              {
-                 if (current->Pcb.State == PROCESS_STATE_TERMINATED)
-                   {
-                     Status = STATUS_PROCESS_IS_TERMINATING;
-                   }
-                 else
-                   {
-                     Status = ObReferenceObjectByPointer(current,
-                                                         DesiredAccess,
-                                                         PsProcessType,
-                                                         UserMode);
-                   }
-                 ExReleaseFastMutex(&PspActiveProcessMutex);
-                 if (NT_SUCCESS(Status))
-                   {
-                     Status = ObCreateHandle(PsGetCurrentProcess(),
-                                             current,
-                                             DesiredAccess,
-                                             FALSE,
-                                             ProcessHandle);
-                     ObDereferenceObject(current);
-                     DPRINT("*ProcessHandle %x\n", ProcessHandle);
-                     DPRINT("NtOpenProcess() = %x\n", Status);
-                   }
-                 return(Status);
-              }
-            current_entry = current_entry->Flink;
-         }
-       ExReleaseFastMutex(&PspActiveProcessMutex);
-       DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
-       return(STATUS_UNSUCCESSFUL);
+       return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
      }
 }
 
@@ -841,11 +524,9 @@ PsGetProcessExitTime(VOID)
  */
 LONGLONG
 STDCALL
-PsGetProcessCreateTimeQuadPart(
-    PEPROCESS  Process
-       )
+PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
 {
-       return Process->CreateTime.QuadPart;
+    return Process->CreateTime.QuadPart;
 }
 
 /*
@@ -853,11 +534,9 @@ PsGetProcessCreateTimeQuadPart(
  */
 PVOID
 STDCALL
-PsGetProcessDebugPort(
-    PEPROCESS  Process
-       )
+PsGetProcessDebugPort(PEPROCESS Process)
 {
-       return Process->DebugPort;
+    return Process->DebugPort;
 }
 
 /*
@@ -865,11 +544,9 @@ PsGetProcessDebugPort(
  */
 BOOLEAN
 STDCALL
-PsGetProcessExitProcessCalled(
-    PEPROCESS  Process
-       )
+PsGetProcessExitProcessCalled(PEPROCESS Process)
 {
-       return Process->ExitProcessCalled;      
+    return Process->ExitProcessCalled; 
 }
 
 /*
@@ -877,11 +554,9 @@ PsGetProcessExitProcessCalled(
  */
 NTSTATUS
 STDCALL
-PsGetProcessExitStatus(
-       PEPROCESS Process
-       )
+PsGetProcessExitStatus(PEPROCESS Process)
 {
-       return Process->ExitStatus;
+    return Process->ExitStatus;
 }
 
 /*
@@ -889,11 +564,9 @@ PsGetProcessExitStatus(
  */
 HANDLE
 STDCALL
-PsGetProcessId(
-       PEPROCESS       Process
-       )
+PsGetProcessId(PEPROCESS Process)
 {
-       return (HANDLE)Process->UniqueProcessId;
+    return (HANDLE)Process->UniqueProcessId;
 }
 
 /*
@@ -901,11 +574,9 @@ PsGetProcessId(
  */
 LPSTR
 STDCALL
-PsGetProcessImageFileName(
-    PEPROCESS  Process
-       )
+PsGetProcessImageFileName(PEPROCESS Process)
 {
-       return (LPSTR)Process->ImageFileName;
+    return (LPSTR)Process->ImageFileName;
 }
 
 /*
@@ -913,11 +584,9 @@ PsGetProcessImageFileName(
  */
 HANDLE
 STDCALL
-PsGetProcessInheritedFromUniqueProcessId(
-    PEPROCESS  Process
-       )
+PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
 {
-       return Process->InheritedFromUniqueProcessId;
+    return Process->InheritedFromUniqueProcessId;
 }
 
 /*
@@ -925,11 +594,9 @@ PsGetProcessInheritedFromUniqueProcessId(
  */
 PEJOB
 STDCALL
-PsGetProcessJob(
-       PEPROCESS Process
-       )
+PsGetProcessJob(PEPROCESS Process)
 {
-       return Process->Job;
+    return Process->Job;
 }
 
 /*
@@ -937,11 +604,9 @@ PsGetProcessJob(
  */
 PPEB
 STDCALL
-PsGetProcessPeb(
-    PEPROCESS  Process
-       )
+PsGetProcessPeb(PEPROCESS Process)
 {
-       return Process->Peb;    
+    return Process->Peb;
 }
 
 /*
@@ -949,47 +614,28 @@ PsGetProcessPeb(
  */
 ULONG
 STDCALL
-PsGetProcessPriorityClass(
-    PEPROCESS  Process
-       )
-{
-       return Process->PriorityClass;
-}
-
-/*
- * @implemented
- */
-PVOID
-STDCALL
-PsGetProcessSectionBaseAddress(
-    PEPROCESS  Process
-       )
+PsGetProcessPriorityClass(PEPROCESS Process)
 {
-       return Process->SectionBaseAddress;
+    return Process->PriorityClass;
 }
 
 /*
  * @implemented
  */
-PVOID
-STDCALL
-PsGetProcessSecurityPort(
-       PEPROCESS Process
-       )
+HANDLE STDCALL
+PsGetCurrentProcessId(VOID)
 {
-       return Process->SecurityPort;
+    return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
 }
 
 /*
  * @implemented
  */
-HANDLE
+ULONG
 STDCALL
-PsGetProcessSessionId(
-    PEPROCESS  Process
-       )
+PsGetCurrentProcessSessionId(VOID)
 {
-       return (HANDLE)Process->SessionId;
+    return PsGetCurrentProcess()->SessionId;
 }
 
 /*
@@ -997,11 +643,9 @@ PsGetProcessSessionId(
  */
 PVOID
 STDCALL
-PsGetProcessWin32Process(
-       PEPROCESS Process
-       )
+PsGetProcessSectionBaseAddress(PEPROCESS Process)
 {
-       return Process->Win32Process;
+    return Process->SectionBaseAddress;
 }
 
 /*
@@ -1009,174 +653,49 @@ PsGetProcessWin32Process(
  */
 PVOID
 STDCALL
-PsGetProcessWin32WindowStation(
-    PEPROCESS  Process
-       )
+PsGetProcessSecurityPort(PEPROCESS Process)
 {
-       return Process->Win32WindowStation;
+    return Process->SecurityPort;
 }
 
 /*
  * @implemented
  */
-BOOLEAN
+HANDLE
 STDCALL
-PsIsProcessBeingDebugged(
-    PEPROCESS  Process
-       )
+PsGetProcessSessionId(PEPROCESS Process)
 {
-       return FALSE/*Process->IsProcessBeingDebugged*/;
+    return (HANDLE)Process->SessionId;
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-PsLookupProcessByProcessId(IN HANDLE ProcessId,
-                          OUT PEPROCESS *Process)
-{
-  PHANDLE_TABLE_ENTRY CidEntry;
-  PEPROCESS FoundProcess;
-
-  PAGED_CODE();
-
-  ASSERT(Process);
-
-  CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
-  if(CidEntry != NULL)
-  {
-    ObReferenceObject(FoundProcess);
-
-    PsUnlockCidHandle(CidEntry);
-
-    *Process = FoundProcess;
-    return STATUS_SUCCESS;
-  }
-
-  return STATUS_INVALID_PARAMETER;
-}
-
-VOID
+PVOID
 STDCALL
-PspRunCreateProcessNotifyRoutines
-(
- PEPROCESS CurrentProcess,
- BOOLEAN Create
-)
+PsGetProcessWin32Process(PEPROCESS Process)
 {
- ULONG i;
- HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
- HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
- for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
-  if(PiProcessNotifyRoutine[i])
-   PiProcessNotifyRoutine[i](ParentId, ProcessId, Create);
+    return Process->Win32Process;
 }
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
-                               IN BOOLEAN Remove)
-{
-  ULONG i;
-
-  if (Remove)
-  {
-     for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
-     {
-        if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
-        {
-           PiProcessNotifyRoutine[i] = NULL;
-           break;
-        }
-     }
-
-     return(STATUS_SUCCESS);
-  }
-
-  /*insert*/
-  for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
-  {
-     if (PiProcessNotifyRoutine[i] == NULL)
-     {
-        PiProcessNotifyRoutine[i] = NotifyRoutine;
-        break;
-     }
-  }
-
-  if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
-  {
-     return STATUS_INSUFFICIENT_RESOURCES;
-  }
-
-  return STATUS_SUCCESS;
-}
-
-VOID STDCALL
-PspRunLoadImageNotifyRoutines(
-   PUNICODE_STRING FullImageName,
-   HANDLE ProcessId,
-   PIMAGE_INFO ImageInfo)
-{
-   ULONG i;
-   for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
-      if (PiLoadImageNotifyRoutine[i])
-         PiLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
-}
-
-/*
- * @unimplemented
- */                       
-NTSTATUS
+PVOID
 STDCALL
-PsRemoveLoadImageNotifyRoutine(
-    IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
-    )
+PsGetProcessWin32WindowStation(PEPROCESS Process)
 {
-       UNIMPLEMENTED;
-       return STATUS_NOT_IMPLEMENTED;  
+    return Process->Win32WindowStation;
 }
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
-{
-   ULONG i;
-
-   for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
-   {
-      if (PiLoadImageNotifyRoutine[i] == NULL)
-      {
-         PiLoadImageNotifyRoutine[i] = NotifyRoutine;
-         break;
-      }
-   }
-
-   if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
-   {
-      return STATUS_INSUFFICIENT_RESOURCES;
-   }
-
-   return STATUS_SUCCESS;
-}
-
-/*
- * @implemented
- */                       
-VOID
+BOOLEAN
 STDCALL
-PsSetProcessPriorityClass(
-    PEPROCESS  Process,
-    ULONG      PriorityClass   
-       )
+PsIsProcessBeingDebugged(PEPROCESS Process)
 {
-       Process->PriorityClass = PriorityClass;
+    return FALSE; //Process->IsProcessBeingDebugged;
 }
 
 /*
@@ -1184,25 +703,21 @@ PsSetProcessPriorityClass(
  */                       
 VOID
 STDCALL
-PsSetProcessSecurityPort(
-    PEPROCESS  Process,
-    PVOID      SecurityPort    
-       )
+PsSetProcessPriorityClass(PEPROCESS Process,
+                          ULONG PriorityClass)
 {
-       Process->SecurityPort = SecurityPort;
+    Process->PriorityClass = PriorityClass;
 }
 
 /*
  * @implemented
- */
+ */                       
 VOID
 STDCALL
-PsSetProcessWin32Process(
-    PEPROCESS  Process,
-    PVOID      Win32Process
-       )
+PsSetProcessSecurityPort(PEPROCESS Process,
+                         PVOID SecurityPort)
 {
-       Process->Win32Process = Win32Process;
+    Process->SecurityPort = SecurityPort;
 }
 
 /*
@@ -1210,229 +725,195 @@ PsSetProcessWin32Process(
  */
 VOID
 STDCALL
-PsSetProcessWin32WindowStation(
-    PEPROCESS  Process,
-    PVOID      WindowStation
-       )
+PsSetProcessWin32Process(PEPROCESS Process,
+                         PVOID Win32Process)
 {
-       Process->Win32WindowStation = WindowStation;
+    Process->Win32Process = Win32Process;
 }
 
-/* Pool Quotas */
 /*
  * @implemented
  */
 VOID
 STDCALL
-PsChargePoolQuota(
-    IN PEPROCESS Process,
-    IN POOL_TYPE PoolType,
-    IN ULONG_PTR Amount
-    )
-{
-    NTSTATUS Status;
-
-    /* Charge the usage */
-    Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
-
-    /* Raise Exception */
-    if (!NT_SUCCESS(Status)) {
-        ExRaiseStatus(Status);
-    }
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-PsChargeProcessNonPagedPoolQuota (
-    IN PEPROCESS Process,
-    IN ULONG_PTR Amount
-    )
-{
-    /* Call the general function */
-    return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-STDCALL
-PsChargeProcessPagedPoolQuota (
-    IN PEPROCESS Process,
-    IN ULONG_PTR Amount
-    )
+PsSetProcessWin32WindowStation(PEPROCESS Process,
+                               PVOID WindowStation)
 {
-    /* Call the general function */
-    return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
+    Process->Win32WindowStation = WindowStation;
 }
 
 /*
+ * FUNCTION: Creates a process.
+ * ARGUMENTS:
+ *        ProcessHandle (OUT) = Caller supplied storage for the resulting
+ *                              handle
+ *        DesiredAccess = Specifies the allowed or desired access to the
+ *                        process can be a combination of
+ *                        STANDARD_RIGHTS_REQUIRED| ..
+ *        ObjectAttribute = Initialized attributes for the object, contains
+ *                          the rootdirectory and the filename
+ *        ParentProcess = Handle to the parent process.
+ *        InheritObjectTable = Specifies to inherit the objects of the parent
+ *                             process if true.
+ *        SectionHandle = Handle to a section object to back the image file
+ *        DebugPort = Handle to a DebugPort if NULL the system default debug
+ *                    port will be used.
+ *        ExceptionPort = Handle to a exception port.
+ * REMARKS:
+ *        This function maps to the win32 CreateProcess.
+ * RETURNS: Status
+ *
  * @implemented
  */
-NTSTATUS
+NTSTATUS 
 STDCALL
-PsChargeProcessPoolQuota(
-    IN PEPROCESS Process,
-    IN POOL_TYPE PoolType,
-    IN ULONG_PTR Amount
-    )
-{
-    PEPROCESS_QUOTA_BLOCK QuotaBlock;
-    ULONG NewUsageSize;
-    ULONG NewMaxQuota;
-
-    /* Get current Quota Block */
-    QuotaBlock = Process->QuotaBlock;
-
-    /* Quota Operations are not to be done on the SYSTEM Process */
-    if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
-
-    /* New Size in use */
-    NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
-
-    /* Does this size respect the quota? */
-    if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
-
-        /* It doesn't, so keep raising the Quota */
-        while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) {
-            /* Save new Maximum Quota */
-            QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
-
-            /* See if the new Maximum Quota fulfills our need */
-            if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
+NtCreateProcess(OUT PHANDLE ProcessHandle,
+                IN ACCESS_MASK DesiredAccess,
+                IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+                IN HANDLE ParentProcess,
+                IN BOOLEAN InheritObjectTable,
+                IN HANDLE SectionHandle  OPTIONAL,
+                IN HANDLE DebugPort  OPTIONAL,
+                IN HANDLE ExceptionPort  OPTIONAL)
+{
+    KPROCESSOR_MODE PreviousMode  = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+   
+    PAGED_CODE();
+     
+    /* Check parameters */ 
+    if(PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            ProbeForWrite(ProcessHandle,
+                          sizeof(HANDLE),
+                          sizeof(ULONG));
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
         }
+        _SEH_END;
 
-        return STATUS_QUOTA_EXCEEDED;
+        if(!NT_SUCCESS(Status)) return Status;
     }
-
-QuotaChanged:
-    /* Save new Usage */
-    QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
-
-    /* Is this a new peak? */
-    if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) {
-        QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
+   
+    /* Make sure there's a parent process */
+    if(ParentProcess == NULL)
+    {
+        /* Can't create System Processes like this */
+        Status = STATUS_INVALID_PARAMETER;
     }
-
-    /* All went well */
-    return STATUS_SUCCESS;
+    else
+    {
+        /* Create a user Process */
+        Status = PspCreateProcess(ProcessHandle,
+                                  DesiredAccess,
+                                  ObjectAttributes,
+                                  ParentProcess,
+                                  InheritObjectTable,
+                                  SectionHandle,
+                                  DebugPort,
+                                  ExceptionPort);
+    }
+   
+    /* Return Status */
+    return Status;
 }
 
 /*
- * @unimplemented
- */                       
-VOID
-STDCALL
-PsReturnPoolQuota(
-    IN PEPROCESS Process,
-    IN POOL_TYPE PoolType,
-    IN ULONG_PTR Amount
-    )
-{
-       UNIMPLEMENTED;
-} 
-
-/*
- * @unimplemented
- */                       
-VOID
-STDCALL
-PsReturnProcessNonPagedPoolQuota(
-    IN PEPROCESS Process,
-    IN ULONG_PTR Amount
-    )
-{
-       UNIMPLEMENTED;
-} 
-
-/*
- * @unimplemented
- */                       
-VOID
+ * @implemented
+ */
+NTSTATUS 
 STDCALL
-PsReturnProcessPagedPoolQuota(
-    IN PEPROCESS Process,
-    IN ULONG_PTR Amount
-    )
-{
-       UNIMPLEMENTED;
-}
-
-NTSTATUS
-PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
+NtOpenProcess(OUT PHANDLE ProcessHandle,
+              IN  ACCESS_MASK DesiredAccess,
+              IN  POBJECT_ATTRIBUTES ObjectAttributes,
+              IN  PCLIENT_ID ClientId)
 {
-  ULONG Attempts = 0;
-  PKTHREAD PrevLockOwner;
-  NTSTATUS Status = STATUS_UNSUCCESSFUL;
-  PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
-  PKTHREAD CallingThread = KeGetCurrentThread();
-  
-  PAGED_CODE();
-  
-  KeEnterCriticalRegion();
-  
-  for(;;)
-  {
-    PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
-      &Process->LockOwner, CallingThread, NULL);
-    if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
+    KPROCESSOR_MODE PreviousMode  = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_INVALID_PARAMETER;
+    PEPROCESS Process;
+    PETHREAD Thread = NULL;
+   
+    DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
+           "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
+           ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
+           ClientId->UniqueProcess, ClientId->UniqueThread);
+    PAGED_CODE();
+        
+    /* Open by name if one was given */
+    DPRINT("Checking type\n");
+    if (ObjectAttributes->ObjectName)
     {
-      /* we got the lock or already locked it */
-      if(InterlockedIncrementUL(&Process->LockCount) == 1)
-      {
-        KeClearEvent(&Process->LockEvent);
-      }
-
-      return STATUS_SUCCESS;
+        /* Open it */    
+        DPRINT("Opening by name\n");
+        Status = ObOpenObjectByName(ObjectAttributes,
+                                    PsProcessType,
+                                    NULL,
+                                    PreviousMode,
+                                    DesiredAccess,
+                                    NULL,
+                                    ProcessHandle);
+                                        
+        if (Status != STATUS_SUCCESS)
+        {
+            DPRINT1("Could not open object by name\n");
+        }
+        
+        /* Return Status */
+        DPRINT("Found: %x\n", ProcessHandle);
+        return(Status);
     }
-    else
+    else if (ClientId)
     {
-      if(++Attempts > 2)
-      {
-        Status = KeWaitForSingleObject(&Process->LockEvent,
-                                       Executive,
-                                       KernelMode,
-                                       FALSE,
-                                       Delay);
-        if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
+        /* Open by Thread ID */
+        if (ClientId->UniqueThread)
         {
-#ifndef NDEBUG
-          if(Status == STATUS_TIMEOUT)
-          {
-            DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
-          }
-#endif
-          KeLeaveCriticalRegion();
-          break;
+            /* Get the Process */
+            DPRINT("Opening by Thread ID\n");
+            Status = PsLookupProcessThreadByCid(ClientId,
+                                                &Process,
+                                                &Thread);
+            DPRINT("Found: %x\n", Process);
+        } 
+        else 
+        {
+            /* Get the Process */
+            DPRINT("Opening by Process ID\n");
+            Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
+                                                &Process);
+            DPRINT("Found: %x\n", Process);
         }
-      }
-      else
-      {
-        KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
-      }
+       
+        if(!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failure to find process\n");
+            return Status;
+        }
+       
+        /* Open the Process Object */
+        Status = ObOpenObjectByPointer(Process,
+                                       ObjectAttributes->Attributes,
+                                       NULL,
+                                       0,
+                                       PsProcessType,
+                                       PreviousMode,
+                                       ProcessHandle);
+        if(!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failure to open process\n");
+        }
+                                      
+        /* Dereference the thread if we used it */
+        if (Thread) ObDereferenceObject(Thread);
+        
+        /* Dereference the Process */
+        ObDereferenceObject(Process);
     }
-  }
-  
-  return Status;
-}
-
-VOID
-PsUnlockProcess(PEPROCESS Process)
-{
-  PAGED_CODE();
-  
-  ASSERT(Process->LockOwner == KeGetCurrentThread());
-  
-  if(InterlockedDecrementUL(&Process->LockCount) == 0)
-  {
-    InterlockedExchangePointer(&Process->LockOwner, NULL);
-    KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
-  }
-  
-  KeLeaveCriticalRegion();
+    
+    return Status;
 }
-
 /* EOF */
index d8070ab..7adcef1 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
+extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
+
+static GENERIC_MAPPING PiProcessMapping = {
+    STANDARD_RIGHTS_READ    | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+    STANDARD_RIGHTS_WRITE   | PROCESS_CREATE_PROCESS    | PROCESS_CREATE_THREAD   |
+    PROCESS_VM_OPERATION    | PROCESS_VM_WRITE          | PROCESS_DUP_HANDLE      |
+    PROCESS_TERMINATE       | PROCESS_SET_QUOTA         | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
+    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
+    PROCESS_ALL_ACCESS};
+
+VOID 
+INIT_FUNCTION
+PsInitClientIDManagment(VOID);
+
+VOID STDCALL PspKillMostProcesses();
 /* FUNCTIONS ***************************************************************/
 
 VOID PiShutdownProcessManager(VOID)
 {
    DPRINT("PiShutdownProcessManager()\n");
    
-   PiKillMostProcesses();
+   PspKillMostProcesses();
 }
 
 VOID INIT_FUNCTION
@@ -33,7 +48,177 @@ PiInitProcessManager(VOID)
    PsInitialiseW32Call();
 }
 
+VOID 
+INIT_FUNCTION
+PsInitProcessManagment(VOID)
+{
+   PKPROCESS KProcess;
+   NTSTATUS Status;
+   
+   ShortPsLockDelay.QuadPart = -100LL;
+   PsLockTimeout.QuadPart = -10000000LL; /* one second */
+   /*
+    * Register the process object type
+    */
+   
+   PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+
+   PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
+   PsProcessType->TotalObjects = 0;
+   PsProcessType->TotalHandles = 0;
+   PsProcessType->PeakObjects = 0;
+   PsProcessType->PeakHandles = 0;
+   PsProcessType->PagedPoolCharge = 0;
+   PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
+   PsProcessType->Mapping = &PiProcessMapping;
+   PsProcessType->Dump = NULL;
+   PsProcessType->Open = NULL;
+   PsProcessType->Close = NULL;
+   PsProcessType->Delete = PspDeleteProcess;
+   PsProcessType->Parse = NULL;
+   PsProcessType->Security = NULL;
+   PsProcessType->QueryName = NULL;
+   PsProcessType->OkayToClose = NULL;
+   PsProcessType->Create = NULL;
+   PsProcessType->DuplicationNotify = NULL;
+   
+   RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
+   
+   ObpCreateTypeObject(PsProcessType);
+
+   InitializeListHead(&PsActiveProcessHead);
+   ExInitializeFastMutex(&PspActiveProcessMutex);
+   
+   /*
+    * Initialize the idle process
+    */
+   Status = ObCreateObject(KernelMode,
+                          PsProcessType,
+                          NULL,
+                          KernelMode,
+                          NULL,
+                          sizeof(EPROCESS),
+                          0,
+                          0,
+                          (PVOID*)&PsIdleProcess);
+   if (!NT_SUCCESS(Status))
+     {
+        DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status);
+        KEBUGCHECK(0);
+        return;
+     }
 
+   RtlZeroMemory(PsIdleProcess, sizeof(EPROCESS));
+   
+   PsIdleProcess->Pcb.Affinity = 0xFFFFFFFF;
+   PsIdleProcess->Pcb.IopmOffset = 0xffff;
+   PsIdleProcess->Pcb.LdtDescriptor[0] = 0;
+   PsIdleProcess->Pcb.LdtDescriptor[1] = 0;
+   PsIdleProcess->Pcb.BasePriority = PROCESS_PRIO_IDLE;
+   PsIdleProcess->Pcb.ThreadQuantum = 6;
+   InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
+   InitializeListHead(&PsIdleProcess->ThreadListHead);
+   InitializeListHead(&PsIdleProcess->ProcessListEntry);
+   KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.DispatcherHeader,
+                               ProcessObject,
+                               sizeof(EPROCESS),
+                               FALSE);
+   PsIdleProcess->Pcb.DirectoryTableBase =
+     (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
+   strcpy(PsIdleProcess->ImageFileName, "Idle");
+
+   /*
+    * Initialize the system process
+    */
+   Status = ObCreateObject(KernelMode,
+                          PsProcessType,
+                          NULL,
+                          KernelMode,
+                          NULL,
+                          sizeof(EPROCESS),
+                          0,
+                          0,
+                          (PVOID*)&PsInitialSystemProcess);
+   if (!NT_SUCCESS(Status))
+     {
+        DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status);
+        KEBUGCHECK(0);
+        return;
+     }
+   
+   /* System threads may run on any processor. */
+   PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
+   PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
+   PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
+   PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
+   PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
+   PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
+   InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
+   KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
+                               ProcessObject,
+                               sizeof(EPROCESS),
+                               FALSE);
+   KProcess = &PsInitialSystemProcess->Pcb;
+   
+   MmInitializeAddressSpace(PsInitialSystemProcess,
+                           &PsInitialSystemProcess->AddressSpace);
+   
+   KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
+   PsInitialSystemProcess->LockCount = 0;
+   PsInitialSystemProcess->LockOwner = NULL;
+
+#if defined(__GNUC__)
+   KProcess->DirectoryTableBase = 
+     (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
+#else
+   {
+     LARGE_INTEGER dummy;
+     dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
+     KProcess->DirectoryTableBase = dummy;
+   }
+#endif
+
+   strcpy(PsInitialSystemProcess->ImageFileName, "System");
+   
+   PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
+   
+   InsertHeadList(&PsActiveProcessHead,
+                 &PsInitialSystemProcess->ProcessListEntry);
+   InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
+   
+#ifndef SCHED_REWRITE
+    PTOKEN BootToken;
+        
+    /* No parent, this is the Initial System Process. Assign Boot Token */
+    BootToken = SepCreateSystemProcessToken();
+    BootToken->TokenInUse = TRUE;
+    PsInitialSystemProcess->Token = BootToken;
+    ObReferenceObject(BootToken);
+#endif
+}
+
+VOID
+PspPostInitSystemProcess(VOID)
+{
+  NTSTATUS Status;
+  
+  /* this routine is called directly after the exectuive handle tables were
+     initialized. We'll set up the Client ID handle table and assign the system
+     process a PID */
+  PsInitClientIDManagment();
+  
+  ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess);
+  ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable;
+  
+  Status = PsCreateCidHandle(PsInitialSystemProcess,
+                             PsProcessType,
+                             &PsInitialSystemProcess->UniqueProcessId);
+  if(!NT_SUCCESS(Status))
+  {
+    DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
+    KEBUGCHECK(0);
+  }
+}
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     PsGetVersion
diff --git a/reactos/ntoskrnl/ps/quota.c b/reactos/ntoskrnl/ps/quota.c
new file mode 100644 (file)
index 0000000..73015e7
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/quota.c
+ * PURPOSE:         Process Pool Quotas
+ * 
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES **************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS ***************************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+PsChargePoolQuota(IN PEPROCESS Process,
+                  IN POOL_TYPE PoolType,
+                  IN ULONG_PTR Amount)
+{
+    NTSTATUS Status;
+
+    /* Charge the usage */
+    Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
+
+    /* Raise Exception */
+    if (!NT_SUCCESS(Status)) 
+    {
+        ExRaiseStatus(Status);
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process,
+                                 IN ULONG_PTR Amount)
+{
+    /* Call the general function */
+    return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+PsChargeProcessPagedPoolQuota(IN PEPROCESS Process,
+                              IN ULONG_PTR Amount)
+{
+    /* Call the general function */
+    return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+PsChargeProcessPoolQuota(IN PEPROCESS Process,
+                         IN POOL_TYPE PoolType,
+                         IN ULONG_PTR Amount)
+{
+    PEPROCESS_QUOTA_BLOCK QuotaBlock;
+    ULONG NewUsageSize;
+    ULONG NewMaxQuota;
+
+    /* Get current Quota Block */
+    QuotaBlock = Process->QuotaBlock;
+
+    /* Quota Operations are not to be done on the SYSTEM Process */
+    if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
+
+    /* New Size in use */
+    NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
+
+    /* Does this size respect the quota? */
+    if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) 
+    {
+        /* It doesn't, so keep raising the Quota */
+        while (MiRaisePoolQuota(PoolType, 
+               QuotaBlock->QuotaEntry[PoolType].Limit, 
+               &NewMaxQuota)) 
+        {
+            /* Save new Maximum Quota */
+            QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
+
+            /* See if the new Maximum Quota fulfills our need */
+            if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
+        }
+
+        return STATUS_QUOTA_EXCEEDED;
+    }
+
+QuotaChanged:
+    /* Save new Usage */
+    QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
+
+    /* Is this a new peak? */
+    if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) 
+    {
+        QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
+    }
+
+    /* All went well */
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @unimplemented
+ */                       
+VOID
+STDCALL
+PsReturnPoolQuota(IN PEPROCESS Process,
+                  IN POOL_TYPE PoolType,
+                  IN ULONG_PTR Amount)
+{
+    UNIMPLEMENTED;
+} 
+
+/*
+ * @unimplemented
+ */                       
+VOID
+STDCALL
+PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process,
+                                 IN ULONG_PTR Amount)
+{
+    UNIMPLEMENTED;
+} 
+
+/*
+ * @unimplemented
+ */                       
+VOID
+STDCALL
+PsReturnProcessPagedPoolQuota(IN PEPROCESS Process,
+                              IN ULONG_PTR Amount)
+{
+    UNIMPLEMENTED;
+}
+
+/* EOF */
index 579a5c2..be6707d 100644 (file)
@@ -18,9 +18,6 @@ ULONG
 STDCALL
 KeResumeThread(PKTHREAD Thread);
 
-ULONG
-STDCALL
-KeSuspendThread(PKTHREAD Thread);
 /* FUNCTIONS *****************************************************************/
 
 /*
index b5583c7..b2a69f9 100644 (file)
@@ -428,6 +428,573 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
           Id, IdleThread->Cid.UniqueThread);
 }
 
+VOID
+PiBeforeBeginThread(CONTEXT c)
+{
+    KeLowerIrql(PASSIVE_LEVEL);
+}
+
+NTSTATUS
+PsInitializeThread (
+    PEPROCESS Process,
+    PETHREAD* ThreadPtr,
+    POBJECT_ATTRIBUTES ObjectAttributes,
+    KPROCESSOR_MODE AccessMode,
+    BOOLEAN First )
+{
+    PETHREAD Thread;
+    NTSTATUS Status;
+    KIRQL oldIrql;
+
+    PAGED_CODE();
+
+    if (Process == NULL)
+    {
+        Process = PsInitialSystemProcess;
+    }
+
+    /*
+    * Create and initialize thread
+    */
+    Status = ObCreateObject(AccessMode,
+        PsThreadType,
+        ObjectAttributes,
+        KernelMode,
+        NULL,
+        sizeof(ETHREAD),
+        0,
+        0,
+        (PVOID*)&Thread);
+    if (!NT_SUCCESS(Status))
+    {
+        return(Status);
+    }
+
+    /*
+    * Reference process
+    */
+    ObReferenceObjectByPointer(Process,
+        PROCESS_CREATE_THREAD,
+        PsProcessType,
+        KernelMode);
+
+    Thread->ThreadsProcess = Process;
+    Thread->Cid.UniqueThread = NULL;
+    Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+
+    DPRINT("Thread = %x\n",Thread);
+
+    KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
+    InitializeListHead(&Thread->ActiveTimerListHead);
+    KeInitializeSpinLock(&Thread->ActiveTimerListLock);
+    InitializeListHead(&Thread->IrpList);
+    Thread->DeadThread = FALSE;
+    Thread->HasTerminated = FALSE;
+    Thread->Tcb.Win32Thread = NULL;
+    DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
+
+
+    Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority;
+    Thread->Tcb.Priority = Thread->Tcb.BasePriority;
+
+    /*
+    * Local Procedure Call facility (LPC)
+    */
+    KeInitializeSemaphore  (& Thread->LpcReplySemaphore, 0, LONG_MAX);
+    Thread->LpcReplyMessage = NULL;
+    Thread->LpcReplyMessageId = 0; /* not valid */
+    /* Thread->LpcReceiveMessageId = 0; */
+    Thread->LpcExitThreadCalled = FALSE;
+    Thread->LpcReceivedMsgIdValid = FALSE;
+
+    oldIrql = KeAcquireDispatcherDatabaseLock();
+    InsertTailList(&Process->ThreadListHead,
+        &Thread->ThreadListEntry);
+    KeReleaseDispatcherDatabaseLock(oldIrql);
+
+    *ThreadPtr = Thread;
+
+    return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+PsCreateTeb (
+    HANDLE ProcessHandle,
+    PTEB *TebPtr,
+    PETHREAD Thread,
+    PINITIAL_TEB InitialTeb )
+{
+    PEPROCESS Process;
+    NTSTATUS Status;
+    ULONG ByteCount;
+    ULONG RegionSize;
+    ULONG TebSize;
+    PVOID TebBase;
+    TEB Teb;
+
+    PAGED_CODE();
+
+    TebSize = PAGE_SIZE;
+
+    if (NULL == Thread->ThreadsProcess)
+    {
+    /* We'll be allocating a 64k block here and only use 4k of it, but this
+    path should almost never be taken. Actually, I never saw it was taken,
+    so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and
+        move on */
+        TebBase = NULL;
+        Status = ZwAllocateVirtualMemory(ProcessHandle,
+            &TebBase,
+            0,
+            &TebSize,
+            MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
+            PAGE_READWRITE);
+        if (! NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to allocate virtual memory for TEB\n");
+            return Status;
+        }
+    }
+    else
+    {
+        Process = Thread->ThreadsProcess;
+        PsLockProcess(Process, FALSE);
+        if (NULL == Process->TebBlock ||
+            Process->TebBlock == Process->TebLastAllocated)
+        {
+            Process->TebBlock = NULL;
+            RegionSize = MM_VIRTMEM_GRANULARITY;
+            Status = ZwAllocateVirtualMemory(ProcessHandle,
+                &Process->TebBlock,
+                0,
+                &RegionSize,
+                MEM_RESERVE | MEM_TOP_DOWN,
+                PAGE_READWRITE);
+            if (! NT_SUCCESS(Status))
+            {
+                PsUnlockProcess(Process);
+                DPRINT1("Failed to reserve virtual memory for TEB\n");
+                return Status;
+            }
+            Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize);
+        }
+        TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE);
+        Status = ZwAllocateVirtualMemory(ProcessHandle,
+            &TebBase,
+            0,
+            &TebSize,
+            MEM_COMMIT,
+            PAGE_READWRITE);
+        if (! NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to commit virtual memory for TEB\n");
+            return Status;
+        }
+        Process->TebLastAllocated = TebBase;
+        PsUnlockProcess(Process);
+    }
+
+    DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
+    ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize);
+
+    RtlZeroMemory(&Teb, sizeof(TEB));
+    /* set all pointers to and from the TEB */
+    Teb.Tib.Self = TebBase;
+    if (Thread->ThreadsProcess)
+    {
+        Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
+    }
+    DPRINT("Teb.Peb %x\n", Teb.Peb);
+
+    /* store stack information from InitialTeb */
+    if(InitialTeb != NULL)
+    {
+        /* fixed-size stack */
+        if(InitialTeb->StackBase && InitialTeb->StackLimit)
+        {
+            Teb.Tib.StackBase = InitialTeb->StackBase;
+            Teb.Tib.StackLimit = InitialTeb->StackLimit;
+            Teb.DeallocationStack = InitialTeb->StackLimit;
+        }
+        /* expandable stack */
+        else
+        {
+            Teb.Tib.StackBase = InitialTeb->StackCommit;
+            Teb.Tib.StackLimit = InitialTeb->StackCommitMax;
+            Teb.DeallocationStack = InitialTeb->StackReserved;
+        }
+    }
+
+    /* more initialization */
+    Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
+    Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
+    Teb.CurrentLocale = PsDefaultThreadLocaleId;
+
+    /* Terminate the exception handler list */
+    Teb.Tib.ExceptionList = (PVOID)-1;
+
+    DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
+
+    /* write TEB data into teb page */
+    Status = NtWriteVirtualMemory(ProcessHandle,
+        TebBase,
+        &Teb,
+        sizeof(TEB),
+        &ByteCount);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* free TEB */
+        DPRINT1 ("Writing TEB failed!\n");
+
+        RegionSize = 0;
+        NtFreeVirtualMemory(ProcessHandle,
+            TebBase,
+            &RegionSize,
+            MEM_RELEASE);
+
+        return Status;
+    }
+
+    if (TebPtr != NULL)
+    {
+        *TebPtr = (PTEB)TebBase;
+    }
+
+    DPRINT("TEB allocated at %p\n", TebBase);
+
+    return Status;
+}
+
+
+VOID STDCALL
+LdrInitApcRundownRoutine ( PKAPC Apc )
+{
+    ExFreePool(Apc);
+}
+
+
+VOID STDCALL
+LdrInitApcKernelRoutine (
+    PKAPC Apc,
+    PKNORMAL_ROUTINE* NormalRoutine,
+    PVOID* NormalContext,
+    PVOID* SystemArgument1,
+    PVOID* SystemArgument2)
+{
+    ExFreePool(Apc);
+}
+
+
+NTSTATUS STDCALL
+NtCreateThread (
+    OUT PHANDLE ThreadHandle,
+    IN ACCESS_MASK DesiredAccess,
+    IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+    IN HANDLE ProcessHandle,
+    OUT PCLIENT_ID ClientId,
+    IN PCONTEXT ThreadContext,
+    IN PINITIAL_TEB InitialTeb,
+    IN BOOLEAN CreateSuspended )
+{
+    HANDLE hThread;
+    CONTEXT SafeContext;
+    INITIAL_TEB SafeInitialTeb;
+    PEPROCESS Process;
+    PETHREAD Thread;
+    PTEB TebBase;
+    PKAPC LdrInitApc;
+    KIRQL oldIrql;
+    KPROCESSOR_MODE PreviousMode;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    PAGED_CODE();
+
+    if(ThreadContext == NULL)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    PreviousMode = ExGetPreviousMode();
+
+    if(PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            ProbeForWrite(ThreadHandle,
+                sizeof(HANDLE),
+                sizeof(ULONG));
+            if(ClientId != NULL)
+            {
+                ProbeForWrite(ClientId,
+                    sizeof(CLIENT_ID),
+                    sizeof(ULONG));
+            }
+            ProbeForRead(ThreadContext,
+                sizeof(CONTEXT),
+                sizeof(ULONG));
+            SafeContext = *ThreadContext;
+            ThreadContext = &SafeContext;
+            ProbeForRead(InitialTeb,
+                sizeof(INITIAL_TEB),
+                sizeof(ULONG));
+            SafeInitialTeb = *InitialTeb;
+            InitialTeb = &SafeInitialTeb;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if(!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+    }
+
+    DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
+        ThreadHandle,ThreadContext);
+
+    Status = ObReferenceObjectByHandle(
+        ProcessHandle,
+        PROCESS_CREATE_THREAD,
+        PsProcessType,
+        PreviousMode,
+        (PVOID*)&Process,
+        NULL);
+    if(!NT_SUCCESS(Status))
+    {
+        return(Status);
+    }
+
+    Status = PsLockProcess(Process, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(Process);
+        return(Status);
+    }
+
+    if(Process->ExitTime.QuadPart != 0)
+    {
+        PsUnlockProcess(Process);
+        return STATUS_PROCESS_IS_TERMINATING;
+    }
+
+    PsUnlockProcess(Process);
+
+    Status = PsInitializeThread(Process,
+        &Thread,
+        ObjectAttributes,
+        PreviousMode,
+        FALSE);
+
+    ObDereferenceObject(Process);
+
+    if (!NT_SUCCESS(Status))
+    {
+        return(Status);
+    }
+
+    /* create a client id handle */
+    Status = PsCreateCidHandle (
+        Thread, PsThreadType, &Thread->Cid.UniqueThread);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(Thread);
+        return Status;
+    }
+
+    Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
+    if (!NT_SUCCESS(Status))
+    {
+        PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+        ObDereferenceObject(Thread);
+        return(Status);
+    }
+
+    Status = PsCreateTeb(ProcessHandle,
+        &TebBase,
+        Thread,
+        InitialTeb);
+    if (!NT_SUCCESS(Status))
+    {
+        PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+        ObDereferenceObject(Thread);
+        return(Status);
+    }
+    Thread->Tcb.Teb = TebBase;
+
+    Thread->StartAddress = NULL;
+
+    /*
+    * Maybe send a message to the process's debugger
+    */
+    DbgkCreateThread((PVOID)ThreadContext->Eip);
+
+    /*
+    * First, force the thread to be non-alertable for user-mode alerts.
+    */
+    Thread->Tcb.Alertable = FALSE;
+
+    /*
+    * If the thread is to be created suspended then queue an APC to
+    * do the suspend before we run any userspace code.
+    */
+    if (CreateSuspended)
+    {
+        KeSuspendThread(&Thread->Tcb);
+    }
+
+    /*
+    * Queue an APC to the thread that will execute the ntdll startup
+    * routine.
+    */
+    LdrInitApc = ExAllocatePoolWithTag (
+        NonPagedPool, sizeof(KAPC), TAG('K', 'a', 'p', 'c'));
+    KeInitializeApc (
+        LdrInitApc,
+        &Thread->Tcb,
+        OriginalApcEnvironment,
+        LdrInitApcKernelRoutine,
+        LdrInitApcRundownRoutine,
+        LdrpGetSystemDllEntryPoint(),
+        UserMode,
+        NULL );
+    KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT);
+    /*
+    * The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE.
+    * We must do this manually. Do NOT attempt to set the Thread to Alertable before the call,
+    * doing so is a blatant and erronous hack.
+    */
+    Thread->Tcb.ApcState.UserApcPending = TRUE;
+    Thread->Tcb.Alerted[KernelMode] = TRUE;
+
+    oldIrql = KeAcquireDispatcherDatabaseLock ();
+    KiUnblockThread(&Thread->Tcb, NULL, 0);
+    KeReleaseDispatcherDatabaseLock(oldIrql);
+
+    Status = ObInsertObject((PVOID)Thread,
+        NULL,
+        DesiredAccess,
+        0,
+        NULL,
+        &hThread);
+    if(NT_SUCCESS(Status))
+    {
+        _SEH_TRY
+        {
+            if(ClientId != NULL)
+            {
+                *ClientId = Thread->Cid;
+            }
+            *ThreadHandle = hThread;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+    }
+
+    return Status;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsCreateSystemThread (
+    PHANDLE ThreadHandle,
+    ACCESS_MASK DesiredAccess,
+    POBJECT_ATTRIBUTES ObjectAttributes,
+    HANDLE ProcessHandle,
+    PCLIENT_ID ClientId,
+    PKSTART_ROUTINE StartRoutine,
+    PVOID StartContext )
+/*
+ * FUNCTION: Creates a thread which executes in kernel mode
+ * ARGUMENTS:
+ *       ThreadHandle (OUT) = Caller supplied storage for the returned thread
+ *                            handle
+ *       DesiredAccess = Requested access to the thread
+ *       ObjectAttributes = Object attributes (optional)
+ *       ProcessHandle = Handle of process thread will run in
+ *                       NULL to use system process
+ *       ClientId (OUT) = Caller supplied storage for the returned client id
+ *                        of the thread (optional)
+ *       StartRoutine = Entry point for the thread
+ *       StartContext = Argument supplied to the thread when it begins
+ *                     execution
+ * RETURNS: Success or failure status
+ */
+{
+    PETHREAD Thread;
+    NTSTATUS Status;
+    KIRQL oldIrql;
+
+    PAGED_CODE();
+
+    DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
+        ThreadHandle,ProcessHandle);
+
+    Status = PsInitializeThread(
+        NULL,
+        &Thread,
+        ObjectAttributes,
+        KernelMode,
+        FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        return(Status);
+    }
+
+    /* Set the thread as a system thread */
+    Thread->SystemThread = TRUE;
+
+    Status = PsCreateCidHandle(Thread,
+        PsThreadType,
+        &Thread->Cid.UniqueThread);
+    if(!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(Thread);
+        return Status;
+    }
+
+    Thread->StartAddress = StartRoutine;
+    Status = KiArchInitThread (
+        &Thread->Tcb, StartRoutine, StartContext);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(Thread);
+        return(Status);
+    }
+
+    if (ClientId != NULL)
+    {
+        *ClientId=Thread->Cid;
+    }
+
+    oldIrql = KeAcquireDispatcherDatabaseLock ();
+    KiUnblockThread(&Thread->Tcb, NULL, 0);
+    KeReleaseDispatcherDatabaseLock(oldIrql);
+
+    Status = ObInsertObject(
+        (PVOID)Thread,
+        NULL,
+        DesiredAccess,
+        0,
+        NULL,
+        ThreadHandle);
+
+    /* don't dereference the thread, the initial reference serves as the keep-alive
+    reference which will be removed by the thread reaper */
+
+    return Status;
+}
+
 VOID INIT_FUNCTION
 PsInitThreadManagment(VOID)
 /*