Thread/Process Termination/Repeaing Rewrite + Fixes
authorAlex Ionescu <aionescu@gmail.com>
Fri, 18 Mar 2005 05:53:04 +0000 (05:53 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Fri, 18 Mar 2005 05:53:04 +0000 (05:53 +0000)
---------------------------------------------------

    - ps/cid.c:
            * Moved CID Lookup functions here

    - ps/security.c:
            * Moved all security related functions here. Makes other files neater and security functions
              easier to locate.

    - ps/thread.c:
            * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and
              renamed functions from Ps to Ki.
            * Implemented PsIsSystemThread.
            * Removed Reaper Thread Init (now obsolete).
            * Renamed PiDeleteThread to PspDeleteThread.
            * Moved Thread State functions from tinfo.c to here.

    - ps/process.c:
            * Removed Query/Set Process functions and moved to ps/query.c
            * Renamed PiDeletePRocess to PspDeleteProcess
            * Removed obsoleted Process Termination functions, moved persistent one to kill.c

    - ps/create.c:
            * Moved the security APIs to security.c
            * Correctly implemented PsCreateSystemThread to actually create system threads.

    - ps/suspend.c
            * Rewrote Nt Executive functions to use Kernel functions.
            * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in
              some aspects, especially the issue of the APC looping around the KeWaitXxx call and the
              fact that the routines excluded/ignored the FreezeCount.

    - ps/debug.c
            * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed
              when called and did not work at all. Suspend Regression test now works.
            * Moved Context<->TrapFrame functions to ke/i386/
            * Combined Set/GetThreadContext APCs into a single one, and used special context structure.

    - ps/query.c:
            * Moved Thread/Process Query/Set Routines here.

    - ps/tinfo.c:
            * Removed.

    - ps/kill.c
            * Removed complicated Process Termination semantics and useless Attach/Detach in favor for
              a much more lightweight function which performs the same tasks as before and actually works.
              TaskManager can now terminate foreign processes.
            * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled
              thread. This results in much less code as well as an increase in speed and less micro
              management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without
              requiring masks that were added as hacks to allow it.
            * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new
              termination code.
            * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done
              by Hartmut.
            * Added PspDeletethread here.
            * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out-
              lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions,
              actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown,
              and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate
              Thread as documented.
            * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to
              be compatible with the changes above.
            * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described
              above, and moved each subsystem specific termination helper into its own subsytem.
            * Improved NtTerminateProcess and added more debugging messages.
            * Improved NtTerminateThread and added check against System Thread and made it compatible with
              new implementation.
            * Corrected PsTerminateSystemThread now that we support System Threads.
            * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the
              port, and added tag to pool allocation (documented in pooltag.txt)

    include/internal/*.h:

            * Defined Scheduler Functions and misc new functions or renamed functions.

    ke/apc.c:

            * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated
              to a thread, as well as their APCs and DPCs.

    REGRESSIONS FOUND: NONE

    BUGS/REGRESSIOSN FIXED:
                * Thread/Get Set Context now works.
                * Suspend Regression test now works.
                * Task manager can now kill foreign processes, even hung ones (like it should).
                * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks.
      KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right
                  places. I just wanted to have this first part ready first, so that it won't get too big.

svn path=/trunk/; revision=14174

30 files changed:
reactos/ntoskrnl/Makefile
reactos/ntoskrnl/cm/ntfunc.c
reactos/ntoskrnl/ex/timer.c
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/ob.h
reactos/ntoskrnl/include/internal/port.h
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/dpc.c
reactos/ntoskrnl/ke/i386/exp.c
reactos/ntoskrnl/ke/i386/tskswitch.S
reactos/ntoskrnl/ke/kthread.c
reactos/ntoskrnl/ke/main.c
reactos/ntoskrnl/ke/process.c
reactos/ntoskrnl/ke/queue.c
reactos/ntoskrnl/ke/wait.c
reactos/ntoskrnl/ob/handle.c
reactos/ntoskrnl/ps/cid.c
reactos/ntoskrnl/ps/create.c
reactos/ntoskrnl/ps/debug.c
reactos/ntoskrnl/ps/idle.c
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/ps/process.c
reactos/ntoskrnl/ps/psmgr.c
reactos/ntoskrnl/ps/query.c [new file with mode: 0644]
reactos/ntoskrnl/ps/security.c [new file with mode: 0644]
reactos/ntoskrnl/ps/suspend.c
reactos/ntoskrnl/ps/thread.c
reactos/ntoskrnl/ps/tinfo.c [deleted file]

index 96e3f2a..43a1e17 100644 (file)
@@ -226,9 +226,10 @@ OBJECTS_PS = \
        ps/locale.o \
        ps/process.o \
        ps/psmgr.o \
+       ps/query.o \
+       ps/security.o \
        ps/suspend.o \
        ps/thread.o \
-       ps/tinfo.o \
        ps/win32.o \
        ps/w32call.o
 
index d69c10b..7add480 100644 (file)
@@ -2003,6 +2003,34 @@ NtNotifyChangeKey (IN HANDLE KeyHandle,
        return(STATUS_NOT_IMPLEMENTED);
 }
 
+#if 0
+NTSTATUS STDCALL
+NtNotifyChangeKey (IN HANDLE KeyHandle,
+                  IN HANDLE Event,
+                  IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+                  IN PVOID ApcContext OPTIONAL,
+                  OUT PIO_STATUS_BLOCK IoStatusBlock,
+                  IN ULONG CompletionFilter,
+                  IN BOOLEAN WatchSubtree,
+                  OUT PVOID Buffer,
+                  IN ULONG Length,
+                  IN BOOLEAN Asynchronous)
+{
+     return NtNotifyChangeMultipleKeys(KeyHandle,          
+                                       0,
+                                       NULL,
+                                       Event,
+                                       ApcRoutine,
+                                       ApcContext,
+                                       IoStatusBlock,
+                                       CompletionFilter,
+                                       WatchTree,
+                                       Buffer,
+                                       Length,
+                                       Asynchronous);
+}
+
+#endif
 
 NTSTATUS STDCALL
 NtQueryMultipleValueKey (IN HANDLE KeyHandle,
index 10cf2b9..e5878f6 100644 (file)
@@ -53,6 +53,66 @@ static const INFORMATION_CLASS_INFO ExTimerInfoClass[] = {
 
 /* FUNCTIONS *****************************************************************/
 
+VOID
+STDCALL
+ExTimerRundown(VOID)
+{
+    PETHREAD Thread = PsGetCurrentThread();
+    KIRQL OldIrql;
+    PLIST_ENTRY CurrentEntry;
+    BOOLEAN KillTimer = FALSE;
+    PETIMER Timer;
+    
+    /* Lock the Thread's Active Timer List*/
+    KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
+    
+    /* Loop through all the timers */
+    CurrentEntry = Thread->ActiveTimerListHead.Flink;
+    while (CurrentEntry != &Thread->ActiveTimerListHead) {
+    
+        /* Get the Timer */
+        Timer = CONTAINING_RECORD(CurrentEntry, ETIMER, ActiveTimerListEntry);
+        DPRINT("Timer, ThreadList: %x, %x\n", Timer, Thread);
+        
+        /* Unlock the list */
+        KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
+            
+        /* Lock the Timer */
+        KeAcquireSpinLock(&Timer->Lock, &OldIrql);
+        
+        /* Relock the active list */
+        KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
+        
+        /* Make sure it's associated to us */
+        if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread)) {
+        
+            /* Remove it */
+            DPRINT("Removing from Thread: %x\n", Thread);
+            RemoveEntryList(&Thread->ActiveTimerListHead); 
+            KeCancelTimer(&Timer->KeTimer);
+            KeRemoveQueueDpc(&Timer->TimerDpc);
+            KeRemoveQueueApc(&Timer->TimerApc);   
+            Timer->ApcAssociated = FALSE;      
+            KillTimer = TRUE;
+        }
+                       
+        /* Unlock the list */
+        KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
+        
+        /* Unlock the Timer */
+        KeReleaseSpinLock(&Timer->Lock, OldIrql);
+        
+        /* Dereference it, if needed */
+        if (KillTimer) ObDereferenceObject(Timer);
+        
+        /* Loop again */
+        KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
+        CurrentEntry = CurrentEntry->Flink;
+    }       
+    
+    KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
+}
+
 VOID
 STDCALL
 ExpDeleteTimer(PVOID ObjectBody)
index c2d17e9..4fe107e 100644 (file)
@@ -185,6 +185,10 @@ ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation);
 NTSTATUS
 ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId);
 
+VOID
+STDCALL
+ExTimerRundown(VOID);
+
 #define InterlockedDecrementUL(Addend) \
    (ULONG)InterlockedDecrement((PLONG)(Addend))
 
index 4a3d1e7..305d46f 100644 (file)
@@ -49,6 +49,35 @@ struct _KEXCEPTION_FRAME;
 #define IPI_REQUEST_DPC                    2
 #define IPI_REQUEST_FREEZE         3
 
+/* threadsch.c ********************************************************************/
+
+/* Thread Scheduler Functions */
+
+/* Readies a Thread for Execution. */
+VOID 
+STDCALL
+KiDispatchThreadNoLock(ULONG NewThreadStatus);
+
+/* Readies a Thread for Execution. */
+VOID 
+STDCALL
+KiDispatchThread(ULONG NewThreadStatus);
+
+/* Puts a Thread into a block state. */
+VOID
+STDCALL
+KiBlockThread(PNTSTATUS Status, 
+              UCHAR Alertable, 
+              ULONG WaitMode,
+              UCHAR WaitReason);
+    
+/* Removes a thread out of a block state. */        
+VOID
+STDCALL
+KiUnblockThread(PKTHREAD Thread, 
+                PNTSTATUS WaitStatus, 
+                KPRIORITY Increment);
+
 /* ipi.c ********************************************************************/
 
 BOOLEAN STDCALL 
@@ -150,6 +179,29 @@ VOID inline FASTCALL KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
 VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
 VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
 
+VOID 
+STDCALL
+KeInitializeThread(struct _KPROCESS* Process, PKTHREAD Thread, BOOLEAN First);
+
+VOID
+STDCALL
+KeRundownThread(VOID);
+
+NTSTATUS KeReleaseThread(PKTHREAD Thread);
+
+VOID
+STDCALL
+KeStackAttachProcess (
+    IN struct _KPROCESS* Process,
+    OUT PKAPC_STATE ApcState
+    );
+
+VOID
+STDCALL
+KeUnstackDetachProcess (
+    IN PKAPC_STATE ApcState
+    );
+
 BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment);
 VOID STDCALL KeExpireTimers(PKDPC Apc,
                            PVOID Arg1,
@@ -165,6 +217,10 @@ FASTCALL
 KiAbortWaitThread(PKTHREAD Thread, 
                   NTSTATUS WaitStatus,
                   KPRIORITY Increment);
+                  
+ULONG
+STDCALL
+KeForceResumeThread(IN PKTHREAD Thread);
  
 BOOLEAN STDCALL KiInsertTimer(PKTIMER Timer, LARGE_INTEGER DueTime);
 
@@ -182,6 +238,18 @@ VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
                   PVOID Reserved,
                   PKTRAP_FRAME TrapFrame);
 
+LONG 
+STDCALL 
+KiInsertQueue(IN PKQUEUE Queue, 
+              IN PLIST_ENTRY Entry, 
+              BOOLEAN Head);
+   
+ULONG
+STDCALL
+KeSetProcess(struct _KPROCESS* Process, 
+             KPRIORITY Increment);
+             
+                            
 VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
 
 VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
index 3e4df5e..7e53906 100644 (file)
@@ -302,7 +302,9 @@ ObQueryDeviceMapInformation(PEPROCESS Process, PPROCESS_DEVICEMAP_INFORMATION De
 VOID FASTCALL
 ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent);
 
-
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process);
 /* Security descriptor cache functions */
 
 NTSTATUS
index c987f67..2ac3064 100644 (file)
@@ -29,14 +29,6 @@ typedef struct _EPORT
   ULONG                MaxPoolUsage; /* size of NP zone */
 } EPORT, * PEPORT;
 
-
-typedef struct _EPORT_TERMINATION_REQUEST
-{
-       LIST_ENTRY      ThreadListEntry;
-       PEPORT          Port;   
-} EPORT_TERMINATION_REQUEST, *PEPORT_TERMINATION_REQUEST;
-
-
 typedef struct _EPORT_CONNECT_REQUEST_MESSAGE
 {
   LPC_MESSAGE MessageHeader;
@@ -59,6 +51,11 @@ typedef struct _EPORT_CONNECT_REPLY_MESSAGE
   UCHAR ConnectData[0];
 } EPORT_CONNECT_REPLY_MESSAGE, *PEPORT_CONNECT_REPLY_MESSAGE;
 
+typedef struct _TERMINATION_PORT {
+    LIST_ENTRY Links;
+    PVOID Port;
+} TERMINATION_PORT, *PTERMINATION_PORT;
+
 NTSTATUS STDCALL
 LpcRequestPort (PEPORT         Port,
                PLPC_MESSAGE    LpcMessage);
index 307a0a8..fd8b7b2 100644 (file)
@@ -201,6 +201,7 @@ typedef struct _ETHREAD
   UCHAR ActiveImpersonationInfo;
   ULONG PerformanceCountHigh;
   LIST_ENTRY ThreadListEntry;
+  BOOLEAN SystemThread;
 } ETHREAD;
 
 #include <poppack.h>
@@ -437,7 +438,6 @@ VOID PiShutdownProcessManager(VOID);
 VOID PsInitThreadManagment(VOID);
 VOID PsInitProcessManagment(VOID);
 VOID PsInitIdleThread(VOID);
-VOID PsDispatchThreadNoLock(ULONG NewThreadStatus);
 VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus);
 VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
 VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus);
@@ -458,17 +458,23 @@ PsInitializeThread(PEPROCESS Process,
                   KPROCESSOR_MODE AccessMode,
                   BOOLEAN First);
 
-PACCESS_TOKEN PsReferenceEffectiveToken(PETHREAD Thread,
+PACCESS_TOKEN STDCALL PsReferenceEffectiveToken(PETHREAD Thread,
                                        PTOKEN_TYPE TokenType,
                                        PUCHAR b,
                                        PSECURITY_IMPERSONATION_LEVEL Level);
 
-NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle,
+NTSTATUS STDCALL PsOpenTokenOfProcess(HANDLE ProcessHandle,
                              PACCESS_TOKEN* Token);
-
+VOID
+STDCALL
+PspTerminateProcessThreads(PEPROCESS Process,
+                           NTSTATUS ExitStatus);
 NTSTATUS PsSuspendThread(PETHREAD Thread, PULONG PreviousCount);
 NTSTATUS PsResumeThread(PETHREAD Thread, PULONG PreviousCount);
-
+NTSTATUS
+STDCALL
+PspAssignPrimaryToken(PEPROCESS Process,
+                      HANDLE TokenHandle);
 VOID STDCALL PsExitSpecialApc(PKAPC Apc, 
                      PKNORMAL_ROUTINE *NormalRoutine,
                      PVOID *NormalContext,
@@ -497,27 +503,25 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
 #define PROCESS_PRIO_RT                                18
 
 
-VOID STDCALL
-KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
-NTSTATUS KeReleaseThread(PKTHREAD Thread);
+VOID STDCALL PiDeleteProcess(PVOID ObjectBody);
+
+VOID 
+STDCALL 
+PspReapRoutine(PVOID Context);
 
 VOID
 STDCALL
-KeStackAttachProcess (
-    IN PKPROCESS Process,
-    OUT PKAPC_STATE ApcState
-    );
+PspExitThread(NTSTATUS ExitStatus);
+
+extern LIST_ENTRY PspReaperListHead;
+extern WORK_QUEUE_ITEM PspReaperWorkItem;
+extern BOOLEAN PspReaping;
 
 VOID
 STDCALL
-KeUnstackDetachProcess (
-    IN PKAPC_STATE ApcState
-    );
+PspTerminateThreadByPointer(PETHREAD Thread,
+                            NTSTATUS ExitStatus);
 
-VOID STDCALL PiDeleteProcess(PVOID ObjectBody);
-VOID PsReapThreads(VOID);
-VOID PsInitializeThreadReaper(VOID);
-VOID PsQueueThreadReap(PETHREAD Thread);
 VOID PsUnfreezeOtherThread(PETHREAD Thread);
 VOID PsFreezeOtherThread(PETHREAD Thread);
 VOID PsFreezeProcessThreads(PEPROCESS Process);
@@ -525,19 +529,9 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
 ULONG PsEnumThreadsByProcess(PEPROCESS Process);
 PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
 VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status, 
-              UCHAR Alertable, 
-              ULONG WaitMode,
-              UCHAR WaitReason);
-VOID
-PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment);
-VOID
 PsApplicationProcessorInit(VOID);
 VOID
 PsPrepareForApplicationProcessorInit(ULONG Id);
-VOID
-PsInitReaperThread(VOID);
 VOID STDCALL
 PsIdleThreadMain(PVOID Context);
 
@@ -553,10 +547,19 @@ VOID STDCALL
 PiSuspendThreadNormalRoutine(PVOID NormalContext,
                             PVOID SystemArgument1,
                             PVOID SystemArgument2);
-VOID STDCALL
-PsDispatchThread(ULONG NewThreadStatus);
 VOID
 PsInitialiseSuspendImplementation(VOID);
+NTSTATUS 
+STDCALL
+PspExitProcess(PEPROCESS Process);
+
+VOID 
+STDCALL 
+PspDeleteProcess(PVOID ObjectBody);
+
+VOID 
+STDCALL
+PspDeleteThread(PVOID ObjectBody);
 
 extern LONG PiNrThreadsAwaitingReaping;
 
index daefbad..b2f0626 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
-/* GLOBALS *******************************************************************/
-
-VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
-
 /* FUNCTIONS *****************************************************************/
 
 /*++
@@ -145,19 +141,15 @@ KeInitializeApc(IN PKAPC Apc,
 }
 
 /*++
- * KeInsertQueueApc 
- * @implemented NT4
+ * KiInsertQueueApc 
  *
- *     The KeInsertQueueApc routine queues a APC for execution when the right
+ *     The KiInsertQueueApc routine queues a APC for execution when the right
  *     scheduler environment exists.
  *
  * Params:
  *     Apc - Pointer to an initialized control object of type DPC for which the
  *           caller provides the storage. 
  *
- *     SystemArgument[1,2] - Pointer to a set of two parameters that contain
- *                           untyped data.
- *
  *     PriorityBoost - Priority Boost to apply to the Thread.
  *
  * Returns:
@@ -173,45 +165,16 @@ KeInitializeApc(IN PKAPC Apc,
  *--*/
 BOOLEAN
 STDCALL
-KeInsertQueueApc(PKAPC Apc,
-                 PVOID SystemArgument1,
-                 PVOID SystemArgument2,
+KiInsertQueueApc(PKAPC Apc,
                  KPRIORITY PriorityBoost)
-
 {
-    KIRQL OldIrql;
-    PKTHREAD Thread;
+    PKTHREAD Thread = Apc->Thread;
     PLIST_ENTRY ApcListEntry;
     PKAPC QueuedApc;
-   
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-    DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
-           "SystemArgument2 %x)\n",Apc,SystemArgument1,
-            SystemArgument2);
-
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Get the Thread specified in the APC */
-    Thread = Apc->Thread;
-       
-    /* Make sure the thread allows APC Queues.
-    * The thread is not apc queueable, for instance, when it's (about to be) terminated.
-    */
-    if (Thread->ApcQueueable == FALSE) {
-        DPRINT("Thread doesn't allow APC Queues\n");
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        return FALSE;
-    }
     
-    /* Set the System Arguments */
-    Apc->SystemArgument1 = SystemArgument1;
-    Apc->SystemArgument2 = SystemArgument2;
-
     /* Don't do anything if the APC is already inserted */
     if (Apc->Inserted) {
         
-        KeReleaseDispatcherDatabaseLock(OldIrql);
         return FALSE;
     }
     
@@ -247,7 +210,7 @@ KeInsertQueueApc(PKAPC Apc,
         
         DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
         InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
-                   &Apc->ApcListEntry);
+                       &Apc->ApcListEntry);
     }
     
     /* Confirm Insertion */    
@@ -271,9 +234,9 @@ KeInsertQueueApc(PKAPC Apc,
             DPRINT ("Requesting APC Interrupt for Running Thread \n");
             HalRequestSoftwareInterrupt(APC_LEVEL);
             
-        } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
-                 (Thread->WaitIrql < APC_LEVEL) && 
-                 (Apc->NormalRoutine == NULL)) {
+        } else if ((Thread->State == THREAD_STATE_BLOCKED) && (Thread->WaitIrql == PASSIVE_LEVEL) &&
+                   ((Apc->NormalRoutine == NULL) || 
+                   ((!Thread->KernelApcDisable) && (!Thread->ApcState.KernelApcInProgress)))) {
           
             DPRINT("Waking up Thread for Kernel-Mode APC Delivery \n");
             KiAbortWaitThread(Thread, STATUS_KERNEL_APC, PriorityBoost);
@@ -287,10 +250,79 @@ KeInsertQueueApc(PKAPC Apc,
         Thread->ApcState.UserApcPending = TRUE;
         KiAbortWaitThread(Thread, STATUS_USER_APC, PriorityBoost);
     }
+    
+    return TRUE;
+}
+    
+/*++
+ * KeInsertQueueApc 
+ * @implemented NT4
+ *
+ *     The KeInsertQueueApc routine queues a APC for execution when the right
+ *     scheduler environment exists.
+ *
+ * Params:
+ *     Apc - Pointer to an initialized control object of type DPC for which the
+ *           caller provides the storage. 
+ *
+ *     SystemArgument[1,2] - Pointer to a set of two parameters that contain
+ *                           untyped data.
+ *
+ *     PriorityBoost - Priority Boost to apply to the Thread.
+ *
+ * Returns:
+ *     If the APC is already inserted or APC queueing is disabled, FALSE.
+ *     Otherwise, TRUE.
+ *
+ * Remarks:
+ *     The APC will execute at APC_LEVEL for the KernelRoutine registered, and
+ *     at PASSIVE_LEVEL for the NormalRoutine registered.
+ *
+ *     Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
+ *
+ *--*/
+BOOLEAN
+STDCALL
+KeInsertQueueApc(PKAPC Apc,
+                 PVOID SystemArgument1,
+                 PVOID SystemArgument2,
+                 KPRIORITY PriorityBoost)
+
+{
+    KIRQL OldIrql;
+    PKTHREAD Thread;
+    BOOLEAN Inserted;
+   
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+    DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
+           "SystemArgument2 %x)\n",Apc,SystemArgument1,
+            SystemArgument2);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    
+    /* Get the Thread specified in the APC */
+    Thread = Apc->Thread;
+       
+    /* Make sure the thread allows APC Queues.
+    * The thread is not apc queueable, for instance, when it's (about to be) terminated.
+    */
+    if (Thread->ApcQueueable == FALSE) {
+        DPRINT("Thread doesn't allow APC Queues\n");
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        return FALSE;
+    }
+    
+    /* Set the System Arguments */
+    Apc->SystemArgument1 = SystemArgument1;
+    Apc->SystemArgument2 = SystemArgument2;
+
+    /* Call the Internal Function */
+    Inserted = KiInsertQueueApc(Apc, PriorityBoost);
 
     /* Return Sucess if we are here */
     KeReleaseDispatcherDatabaseLock(OldIrql);
-    return TRUE;
+    return Inserted;
 }
 
 /*++
index 668ffdc..b65e961 100644 (file)
@@ -491,7 +491,7 @@ KiQuantumEnd(VOID)
 
     /* Dispatch the Thread */
     KeLowerIrql(DISPATCH_LEVEL);
-    PsDispatchThread(THREAD_STATE_READY);
+    KiDispatchThread(THREAD_STATE_READY);
 }    
 
 /*
index 0928b08..b61e1f8 100644 (file)
@@ -581,6 +581,125 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
     }
 }
 
+VOID
+KeContextToTrapFrame(PCONTEXT Context,
+                    PKTRAP_FRAME TrapFrame)
+{
+   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+     {
+       TrapFrame->Esp = Context->Esp;
+       TrapFrame->Ss = Context->SegSs;
+       TrapFrame->Cs = Context->SegCs;
+       TrapFrame->Eip = Context->Eip;
+       TrapFrame->Eflags = Context->EFlags;    
+       TrapFrame->Ebp = Context->Ebp;
+     }
+   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+     {
+       TrapFrame->Eax = Context->Eax;
+       TrapFrame->Ebx = Context->Ebx;
+       TrapFrame->Ecx = Context->Ecx;
+       TrapFrame->Edx = Context->Edx;
+       TrapFrame->Esi = Context->Esi;
+       TrapFrame->Edi = Context->Edi;
+     }
+   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+     {
+       TrapFrame->Ds = Context->SegDs;
+       TrapFrame->Es = Context->SegEs;
+       TrapFrame->Fs = Context->SegFs;
+       TrapFrame->Gs = Context->SegGs;
+     }
+   if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
+     {
+       /*
+        * Not handled
+        *
+        * This should be handled separately I think.
+        *  - blight
+        */
+     }
+   if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+     {
+       /*
+        * Not handled
+        */
+     }
+}
+
+VOID
+KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
+                    PCONTEXT Context)
+{
+   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+     {
+       Context->SegSs = TrapFrame->Ss;
+       Context->Esp = TrapFrame->Esp;
+       Context->SegCs = TrapFrame->Cs;
+       Context->Eip = TrapFrame->Eip;
+       Context->EFlags = TrapFrame->Eflags;
+       Context->Ebp = TrapFrame->Ebp;
+     }
+   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+     {
+       Context->Eax = TrapFrame->Eax;
+       Context->Ebx = TrapFrame->Ebx;
+       Context->Ecx = TrapFrame->Ecx;
+       /*
+        * NOTE: In the trap frame which is built on entry to a system
+        * call TrapFrame->Edx will actually hold the address of the
+        * previous TrapFrame. I don't believe leaking this information
+        * has security implications. Also EDX holds the address of the
+        * arguments to the system call in progress so it isn't of much
+        * interest to the debugger.
+        */
+       Context->Edx = TrapFrame->Edx;
+       Context->Esi = TrapFrame->Esi;
+       Context->Edi = TrapFrame->Edi;
+     }
+   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+     {
+       Context->SegDs = TrapFrame->Ds;
+       Context->SegEs = TrapFrame->Es;
+       Context->SegFs = TrapFrame->Fs;
+       Context->SegGs = TrapFrame->Gs;
+     }
+   if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+     {
+       /*
+        * FIXME: Implement this case
+        */     
+       Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
+     }
+   if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
+     {
+       /*
+        * FIXME: Implement this case
+        *
+        * I think this should only be filled for FPU exceptions, otherwise I
+         * would not know where to get it from as it can be the current state
+        * of the FPU or already saved in the thread's FPU save area.
+        *  -blight
+        */
+       Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
+     }
+#if 0
+   if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
+     {
+       /*
+        * FIXME: Investigate this
+        *
+        * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
+        * This should only be filled in case of a SIMD exception I think, so
+        * this is not the right place (like for FPU the state could already be
+        * saved in the thread's FX_SAVE_AREA or still be in the CPU)
+        *  -blight
+        */
+        Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
+     }
+#endif
+}
+
 VOID
 KeDumpStackFrames(PULONG Frame)
 {
index 9e3bf2b..4084b18 100644 (file)
@@ -206,11 +206,6 @@ SaveTrapFrameForKDB_Return:
 
        call    @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
 
-       cmpl    $0, _PiNrThreadsAwaitingReaping
-       je      5f
-       call    _PiWakeupReaperThread@0
-5:
-
        /*
         * Restore the saved register and exit
         */
index cd01714..f8a05ad 100644 (file)
 #include <internal/debug.h>
 
 #define THREAD_ALERT_INCREMENT 2
+
+extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
+
+/*
+ * PURPOSE: List of threads associated with each priority level
+ */
+LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
+static ULONG PriorityListMask = 0;
+ULONG IdleProcessorMask = 0;
+extern BOOLEAN DoneInitYet;
+
 /* FUNCTIONS *****************************************************************/
 
+STATIC 
+VOID
+KiRequestReschedule(CCHAR Processor)
+{
+    PKPCR Pcr;
+
+    Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
+    Pcr->Prcb->QuantumEnd = TRUE;
+    KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
+}
+
+STATIC 
+VOID
+KiInsertIntoThreadList(KPRIORITY Priority, 
+                       PKTHREAD Thread)
+{
+    ASSERT(THREAD_STATE_READY == Thread->State);
+    ASSERT(Thread->Priority == Priority);
+    
+    if (Priority >= MAXIMUM_PRIORITY || Priority < LOW_PRIORITY) {
+        
+        DPRINT1("Invalid thread priority (%d)\n", Priority);
+        KEBUGCHECK(0);
+    }
+    
+    InsertTailList(&PriorityListHead[Priority], &Thread->QueueListEntry);
+    PriorityListMask |= (1 << Priority);
+}
+
+STATIC
+VOID 
+KiRemoveFromThreadList(PKTHREAD Thread)
+{
+    ASSERT(THREAD_STATE_READY == Thread->State);
+    RemoveEntryList(&Thread->QueueListEntry);
+    if (IsListEmpty(&PriorityListHead[(ULONG)Thread->Priority])) {
+        
+        PriorityListMask &= ~(1 << Thread->Priority);
+    }
+}
+
+STATIC
+PKTHREAD 
+KiScanThreadList(KPRIORITY Priority, 
+                 KAFFINITY Affinity)
+{
+    PLIST_ENTRY current_entry;
+    PKTHREAD current;
+    ULONG Mask;
+
+    Mask = (1 << Priority);
+    
+    if (PriorityListMask & Mask) {
+        
+        current_entry = PriorityListHead[Priority].Flink;
+        
+        while (current_entry != &PriorityListHead[Priority]) {
+           
+            current = CONTAINING_RECORD(current_entry, KTHREAD, QueueListEntry);
+            
+            if (current->State != THREAD_STATE_READY) {
+                
+                DPRINT1("%d/%d\n", &current, current->State);
+            }
+            
+            ASSERT(current->State == THREAD_STATE_READY);
+            
+            if (current->Affinity & Affinity) {
+                
+                KiRemoveFromThreadList(current);
+                return(current);
+            }
+            
+            current_entry = current_entry->Flink;
+        }
+    }
+    
+    return(NULL);
+}
+
+VOID 
+STDCALL
+KiDispatchThreadNoLock(ULONG NewThreadStatus)
+{
+    KPRIORITY CurrentPriority;
+    PKTHREAD Candidate;
+    ULONG Affinity;
+    PKTHREAD CurrentThread = KeGetCurrentThread();
+
+    DPRINT("KiDispatchThreadNoLock() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(),
+            CurrentThread, NewThreadStatus, CurrentThread->State);
+
+    CurrentThread->State = (UCHAR)NewThreadStatus;
+    
+    if (NewThreadStatus == THREAD_STATE_READY) {
+            
+        KiInsertIntoThreadList(CurrentThread->Priority,
+                               CurrentThread);
+    }
+
+    Affinity = 1 << KeGetCurrentProcessorNumber();
+    
+    for (CurrentPriority = HIGH_PRIORITY; CurrentPriority >= LOW_PRIORITY; CurrentPriority--) {
+        
+        Candidate = KiScanThreadList(CurrentPriority, Affinity);
+        
+        if (Candidate == CurrentThread) {
+
+            Candidate->State = THREAD_STATE_RUNNING;
+            KeReleaseDispatcherDatabaseLockFromDpcLevel();     
+            return;
+        }
+        
+        if (Candidate != NULL) {
+            
+            PKTHREAD OldThread;
+            PKTHREAD IdleThread;
+
+            DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority);
+
+            Candidate->State = THREAD_STATE_RUNNING;
+
+            OldThread = CurrentThread;
+            CurrentThread = Candidate;
+            IdleThread = KeGetCurrentPrcb()->IdleThread;
+
+            if (OldThread == IdleThread) {
+                
+                IdleProcessorMask &= ~Affinity;
+                
+            } else if (CurrentThread == IdleThread) {
+                
+                IdleProcessorMask |= Affinity;
+            }
+
+            MmUpdatePageDir(PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS));
+
+            /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */
+            KiArchContextSwitch(CurrentThread, OldThread);
+            return;
+        }
+    }
+    
+    DPRINT1("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber());
+    KEBUGCHECK(0);
+}
+
+VOID
+STDCALL
+KiBlockThread(PNTSTATUS Status, 
+              UCHAR Alertable, 
+              ULONG WaitMode,
+              UCHAR WaitReason)
+{
+    PKTHREAD Thread = KeGetCurrentThread();
+    PKWAIT_BLOCK WaitBlock;
+
+    if (Thread->ApcState.KernelApcPending) {
+    
+        DPRINT("Dispatching Thread as ready (APC!)\n");
+        
+        /* Remove Waits */
+        WaitBlock = Thread->WaitBlockList;
+        while (WaitBlock) {
+            RemoveEntryList (&WaitBlock->WaitListEntry);
+            WaitBlock = WaitBlock->NextWaitBlock;
+        }
+        Thread->WaitBlockList = NULL;
+        
+        /* Dispatch it and return status */
+        KiDispatchThreadNoLock (THREAD_STATE_READY);
+        if (Status != NULL) *Status = STATUS_KERNEL_APC;
+
+    } else {
+
+        /* Set the Thread Data as Requested */
+        DPRINT("Dispatching Thread as blocked\n");
+        Thread->Alertable = Alertable;
+        Thread->WaitMode = (UCHAR)WaitMode;
+        Thread->WaitReason = WaitReason;
+        
+        /* Dispatch it and return status */
+        KiDispatchThreadNoLock(THREAD_STATE_BLOCKED);
+        if (Status != NULL) *Status = Thread->WaitStatus;
+    }
+    
+    DPRINT("Releasing Dispatcher Lock\n");
+    KfLowerIrql(Thread->WaitIrql);
+}
+
+VOID 
+STDCALL
+KiDispatchThread(ULONG NewThreadStatus)
+{
+    KIRQL OldIrql;
+
+    if (!DoneInitYet || KeGetCurrentPrcb()->IdleThread == NULL) {
+        return;
+    }
+    
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    KiDispatchThreadNoLock(NewThreadStatus);
+    KeLowerIrql(OldIrql);
+}
+
+VOID
+STDCALL
+KiUnblockThread(PKTHREAD Thread, 
+                PNTSTATUS WaitStatus, 
+                KPRIORITY Increment)
+{
+    if (THREAD_STATE_TERMINATED_1 == Thread->State ||
+        THREAD_STATE_TERMINATED_2 == Thread->State) {
+
+        DPRINT("Can't unblock thread %d because it's terminating\n",
+               Thread->Cid.UniqueThread);
+    
+    } else if (THREAD_STATE_READY == Thread->State ||
+               THREAD_STATE_RUNNING == Thread->State) {
+        
+        DPRINT("Can't unblock thread %d because it's ready or running\n",
+               Thread->Cid.UniqueThread);
+    
+    } else {
+        
+        ULONG Processor;
+        KAFFINITY Affinity;
+
+        /* FIXME: This propably isn't the right way to do it... */
+        /* No it's not... i'll fix it later-- Alex */
+        if (Thread->Priority < LOW_REALTIME_PRIORITY &&
+            Thread->BasePriority < LOW_REALTIME_PRIORITY - 2) {
+          
+            if (!Thread->PriorityDecrement && !Thread->DisableBoost) {
+                
+                Thread->Priority = Thread->BasePriority + Increment;
+                Thread->PriorityDecrement = Increment;
+            }
+            
+        } else {
+            
+            Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
+        }
+     
+        if (WaitStatus != NULL) {
+            
+            Thread->WaitStatus = *WaitStatus;
+        }
+        
+        Thread->State = THREAD_STATE_READY;
+        KiInsertIntoThreadList(Thread->Priority, Thread);
+        Processor = KeGetCurrentProcessorNumber();
+        Affinity = Thread->Affinity;
+        
+        if (!(IdleProcessorMask & (1 << Processor) & Affinity) &&
+             (IdleProcessorMask & ~(1 << Processor) & Affinity)) {
+            
+            ULONG i;
+            
+            for (i = 0; i < KeNumberProcessors - 1; i++) {
+            
+                Processor++;
+                
+                if (Processor >= KeNumberProcessors) {
+                    
+                    Processor = 0;
+                }
+                
+                if (IdleProcessorMask & (1 << Processor) & Affinity) {
+#if 0          
+                    /* FIXME:
+                     *   Reschedule the threads on an other processor 
+                     */
+                    KeReleaseDispatcherDatabaseLockFromDpcLevel();
+                    KiRequestReschedule(Processor);
+                    KeAcquireDispatcherDatabaseLockAtDpcLevel();
+#endif
+                    break;
+                }
+            }
+        } 
+    }
+}
+
+VOID 
+STDCALL
+KiSuspendThreadKernelRoutine(PKAPC Apc,
+                             PKNORMAL_ROUTINE* NormalRoutine,
+                             PVOID* NormalContext,
+                             PVOID* SystemArgument1,
+                             PVOID* SystemArguemnt2)
+{
+}
+
+VOID 
+STDCALL
+KiSuspendThreadNormalRoutine(PVOID NormalContext,
+                             PVOID SystemArgument1,
+                             PVOID SystemArgument2)
+{
+    PKTHREAD CurrentThread = KeGetCurrentThread();
+    
+    /* Non-alertable kernel-mode suspended wait */
+    DPRINT1("Waiting...\n");
+    KeWaitForSingleObject(&CurrentThread->SuspendSemaphore,
+                          Suspended,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+    DPRINT1("Done Waiting\n");
+}
+
+VOID
+STDCALL
+KeRundownThread(VOID)
+{
+    KIRQL OldIrql;
+    PKTHREAD Thread = KeGetCurrentThread();
+    PLIST_ENTRY CurrentEntry;
+    PKMUTANT Mutant;
+    
+    DPRINT("KeRundownThread: %x\n", Thread);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    CurrentEntry = Thread->MutantListHead.Flink;
+    while (CurrentEntry != &Thread->MutantListHead) {
+    
+        /* Get the Mutant */
+        Mutant = CONTAINING_RECORD(CurrentEntry, KMUTANT, MutantListEntry);
+        ASSERT(Mutant->ApcDisable);
+    
+        /* Uncondtionally abandon it */
+        DPRINT("Abandonning the Mutant\n");
+        Mutant->Header.SignalState = 1;
+        Mutant->Abandoned = TRUE;
+        Mutant->OwnerThread = NULL;
+        RemoveEntryList(&Mutant->MutantListEntry);
+        
+        /* Check if the Wait List isn't empty */
+        DPRINT("Checking whether to wake the Mutant\n");
+        if (!IsListEmpty(&Mutant->Header.WaitListHead)) {
+            
+            /* Wake the Mutant */
+            DPRINT("Waking the Mutant\n");
+            KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);
+        }
+    }
+   
+    /* Release the Lock */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+}
+
+ULONG
+STDCALL
+KeResumeThread(PKTHREAD Thread)
+{
+    ULONG PreviousCount;
+    KIRQL OldIrql;
+    
+    DPRINT1("KeResumeThread (Thread %p called). %x, %x\n", Thread, Thread->SuspendCount, Thread->FreezeCount);
+
+    /* Lock the Dispatcher */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Save the Old Count */
+    PreviousCount = Thread->SuspendCount;
+
+    /* Check if it existed */
+    if (PreviousCount) {
+        
+        Thread->SuspendCount--;
+        
+        /* Decrease the current Suspend Count and Check Freeze Count */
+        if ((!Thread->SuspendCount) && (!Thread->FreezeCount)) {
+            
+            /* Signal the Suspend Semaphore */
+            Thread->SuspendSemaphore.Header.SignalState++;
+            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
+        }
+    }
+            
+    /* Release Lock and return the Old State */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    return PreviousCount;
+}
+
+BOOLEAN
+STDCALL
+KiInsertQueueApc(PKAPC Apc,
+                 KPRIORITY PriorityBoost);
+                 
+NTSTATUS
+STDCALL
+KeSuspendThread(PKTHREAD Thread)
+{
+    ULONG PreviousCount;
+    KIRQL OldIrql;
+
+    DPRINT1("KeSuspendThread (Thread %p called). %x, %x\n", Thread, Thread->SuspendCount, Thread->FreezeCount);
+    
+    /* Lock the Dispatcher */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Save the Old Count */
+    PreviousCount = Thread->SuspendCount;
+    
+    /* Increment it */
+    Thread->SuspendCount++;
+    
+    /* Check if we should suspend it */
+    if (!PreviousCount && !Thread->FreezeCount) {
+    
+        /* Insert the APC */
+        if (!KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT)) {
+            
+            /* Unsignal the Semaphore, the APC already got inserted */
+            Thread->SuspendSemaphore.Header.SignalState--;
+        }
+    }
+    
+    /* Release Lock and return the Old State */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    return PreviousCount;
+}
+
+ULONG
+STDCALL
+KeForceResumeThread(IN PKTHREAD Thread)
+{
+    KIRQL OldIrql;
+    ULONG PreviousCount;
+    
+    /* Lock the Dispatcher Database and the APC Queue */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    
+    /* Save the old Suspend Count */
+    PreviousCount = Thread->SuspendCount + Thread->FreezeCount;  
+    
+    /* If the thread is suspended, wake it up!!! */
+    if (PreviousCount) {
+            
+        /* Unwait it completely */
+        Thread->SuspendCount = 0;
+        Thread->FreezeCount = 0;
+            
+        /* Signal and satisfy */
+        Thread->SuspendSemaphore.Header.SignalState++;
+        KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
+    }
+    
+    /* Release Lock and return the Old State */
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    return PreviousCount;
+}
+
 ULONG
 STDCALL
 KeAlertResumeThread(IN PKTHREAD Thread)
@@ -319,9 +787,9 @@ KeInitializeThread(PKPROCESS Process,
     KeInitializeApc(&Thread->SuspendApc,
                     Thread,
                     OriginalApcEnvironment,
-                    PiSuspendThreadKernelRoutine,
-                    PiSuspendThreadRundownRoutine,
-                    PiSuspendThreadNormalRoutine,
+                    KiSuspendThreadKernelRoutine,
+                    NULL,
+                    KiSuspendThreadNormalRoutine,
                     KernelMode,
                     NULL);
      
@@ -462,7 +930,7 @@ KeRevertToUserAffinityThread(VOID)
         
         /* We need to dispatch a new thread */
         CurrentThread->WaitIrql = OldIrql;
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
+        KiDispatchThreadNoLock(THREAD_STATE_READY);
         KeLowerIrql(OldIrql);
     }
 }
@@ -525,11 +993,195 @@ KeSetSystemAffinityThread(IN KAFFINITY Affinity)
         
         /* We need to dispatch a new thread */
         CurrentThread->WaitIrql = OldIrql;
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
+        KiDispatchThreadNoLock(THREAD_STATE_READY);
         KeLowerIrql(OldIrql);
     }
 }
 
+/*
+ * @implemented
+ */
+LONG STDCALL
+KeSetBasePriorityThread (PKTHREAD      Thread,
+                        LONG           Increment)
+/*
+ * Sets thread's base priority relative to the process' base priority
+ * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
+ */
+{
+   KPRIORITY Priority;
+   if (Increment < -2)
+     {
+       Increment = -2;
+     }
+   else if (Increment > 2)
+     {
+       Increment = 2;
+     }
+   Priority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
+   if (Priority < LOW_PRIORITY)
+   {
+     Priority = LOW_PRIORITY;
+   }
+   else if (Priority >= MAXIMUM_PRIORITY)
+     {
+       Thread->BasePriority = HIGH_PRIORITY;
+     }
+   KeSetPriorityThread(Thread, Priority);
+   return 1;
+}
+
+/*
+ * @implemented
+ */
+KPRIORITY 
+STDCALL
+KeSetPriorityThread(PKTHREAD Thread, 
+                    KPRIORITY Priority)
+{
+    KPRIORITY OldPriority;
+    KIRQL OldIrql;
+    PKTHREAD CurrentThread;
+    ULONG Mask;
+    int i;
+    PKPCR Pcr;
+
+    if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY) {
+        
+        KEBUGCHECK(0);
+    }
+
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    OldPriority = Thread->Priority;
+
+    if (OldPriority != Priority) {
+        
+        CurrentThread = KeGetCurrentThread();
+        
+        if (Thread->State == THREAD_STATE_READY) {
+            
+            KiRemoveFromThreadList(Thread);
+            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
+            KiInsertIntoThreadList(Priority, Thread);
+            
+            if (CurrentThread->Priority < Priority) {
+                
+                KiDispatchThreadNoLock(THREAD_STATE_READY);
+                KeLowerIrql(OldIrql);
+                return (OldPriority);
+            }
+        
+        } else if (Thread->State == THREAD_STATE_RUNNING)  {
+            
+            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
+            
+            if (Priority < OldPriority) {
+                
+                /* Check for threads with a higher priority */
+                Mask = ~((1 << (Priority + 1)) - 1);
+                if (PriorityListMask & Mask) {
+                    
+                    if (Thread == CurrentThread) {
+                        
+                        KiDispatchThreadNoLock(THREAD_STATE_READY);
+                        KeLowerIrql(OldIrql);
+                        return (OldPriority);
+                        
+                    } else {
+                        
+                        for (i = 0; i < KeNumberProcessors; i++) {
+                            
+                            Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+                            
+                            if (Pcr->Prcb->CurrentThread == Thread) {
+
+                                KeReleaseDispatcherDatabaseLockFromDpcLevel();
+                                KiRequestReschedule(i);
+                                KeLowerIrql(OldIrql);
+                                return (OldPriority);
+                            }
+                        }
+                    }
+                }
+            }
+        }  else  {
+            
+            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
+        }
+    }
+    
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    return(OldPriority);
+}
+
+/*
+ * @implemented
+ *
+ * Sets thread's affinity
+ */
+NTSTATUS 
+STDCALL
+KeSetAffinityThread(PKTHREAD Thread,
+                    KAFFINITY Affinity)
+{
+    KIRQL OldIrql;
+    ULONG i;
+    PKPCR Pcr;
+    KAFFINITY ProcessorMask;
+
+    DPRINT("KeSetAffinityThread(Thread %x, Affinity %x)\n", Thread, Affinity);
+
+    ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
+
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    Thread->UserAffinity = Affinity;
+    
+    if (Thread->SystemAffinityActive == FALSE) {
+        
+        Thread->Affinity = Affinity;
+        
+        if (Thread->State == THREAD_STATE_RUNNING) {
+            
+            ProcessorMask = 1 << KeGetCurrentKPCR()->ProcessorNumber;
+            if (Thread == KeGetCurrentThread()) {
+                
+                if (!(Affinity & ProcessorMask)) {
+                    
+                    KiDispatchThreadNoLock(THREAD_STATE_READY);
+                    KeLowerIrql(OldIrql);
+                    return STATUS_SUCCESS;
+                }
+                
+            } else {
+                
+                for (i = 0; i < KeNumberProcessors; i++) {
+                    
+                    Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+                    if (Pcr->Prcb->CurrentThread == Thread) {
+                        
+                        if (!(Affinity & ProcessorMask)) {
+                            
+                            KeReleaseDispatcherDatabaseLockFromDpcLevel();
+                            KiRequestReschedule(i);
+                            KeLowerIrql(OldIrql);
+                            return STATUS_SUCCESS;
+                        }
+                        
+                        break;
+                    }
+                }
+
+                ASSERT (i < KeNumberProcessors);
+            }
+        }
+    }
+    
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    return STATUS_SUCCESS;
+}
+
 /*
  * @implemented
  */
@@ -538,8 +1190,45 @@ VOID
 STDCALL
 KeTerminateThread(IN KPRIORITY Increment)
 {
-    /* Call our own internal routine */
-    PsTerminateCurrentThread(0);
+    KIRQL OldIrql;
+    PKTHREAD Thread = KeGetCurrentThread();
+    
+    /* Lock the Dispatcher Database and the APC Queue */
+    DPRINT1("Terminating\n");
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    
+    /* Insert into the Reaper List */
+    InsertTailList(&PspReaperListHead, &((PETHREAD)Thread)->TerminationPortList);
+    
+    /* Check if it's active */
+    if (PspReaping == FALSE) {
+        
+        /* Activate it. We use the internal function for speed, and use the Hyper Critical Queue */
+        PspReaping = TRUE;
+        DPRINT1("Terminating\n");
+        KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,
+                      &PspReaperWorkItem.List,
+                      FALSE);
+    }
+    
+    /* Handle Kernel Queues */
+    if (Thread->Queue) {
+                 
+        DPRINT1("Waking Queue\n");
+        RemoveEntryList(&Thread->QueueListEntry);
+        KiWakeQueue(Thread->Queue);
+    }
+    
+    /* Signal the thread */
+    Thread->DispatcherHeader.SignalState = TRUE;
+    if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE) {
+        
+        /* Satisfy waits */
+        KiWaitTest((PVOID)Thread, Increment);
+    }
+    
+    /* Find a new Thread */
+    KiDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
 }
 
 /*
index b25d272..0efcd83 100644 (file)
@@ -104,7 +104,8 @@ KiSystemStartup(BOOLEAN BootProcessor)
         MiFreeInitMemory();
         
         /* Never returns */
-        PsTerminateSystemThread(STATUS_SUCCESS);
+        PspExitThread(STATUS_SUCCESS);
+        
     } else {
         
         /* Do application processor initialization */
index c523791..49b1aca 100644 (file)
@@ -53,6 +53,35 @@ UpdatePageDirs(PKTHREAD Thread, PKPROCESS Process)
     MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
 }
 
+ULONG
+STDCALL
+KeSetProcess(PKPROCESS Process, 
+             KPRIORITY Increment)
+{
+    KIRQL OldIrql;
+    ULONG OldState;
+    
+    /* Lock Dispatcher */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    
+    /* Get Old State */
+    OldState = Process->DispatcherHeader.SignalState;
+    
+    /* Signal the Process */
+    Process->DispatcherHeader.SignalState = TRUE;
+    if ((OldState == 0) && IsListEmpty(&Process->DispatcherHeader.WaitListHead) != TRUE) {
+        
+        /* Satisfy waits */
+        KiWaitTest((PVOID)Process, Increment);
+    }
+    
+    /* Release Dispatcher Database */    
+    KeReleaseDispatcherDatabaseLock(OldIrql);
+    
+    /* Return the previous State */
+    return OldState;           
+}
+
 /*
  * @implemented
  */
index abfddd9..5f2983d 100644 (file)
@@ -287,7 +287,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
             
             /* Block the Thread */
             DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread);
-            PsBlockThread(&Status, 
+            KiBlockThread(&Status, 
                           FALSE, 
                           WaitMode,
                           WrQueue);
@@ -473,7 +473,7 @@ KiInsertQueue(IN PKQUEUE Queue,
         
         /* Reschedule the Thread */
         DPRINT("Unblocking the Thread\n");
-        PsUnblockThread((PETHREAD)Thread, (PNTSTATUS)&Entry, 0);
+        KiUnblockThread(Thread, (PNTSTATUS)&Entry, 0);
     
     } else {
     
index 9e639db..7ee6920 100644 (file)
@@ -139,7 +139,7 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
 
         /* Block the Thread */
         DPRINT("Blocking the Thread: %d, %d, %x\n", Alertable, WaitMode, KeGetCurrentThread());
-        PsBlockThread(&Status, 
+        KiBlockThread(&Status, 
                       Alertable, 
                       WaitMode, 
                       DelayExecution);
@@ -326,7 +326,7 @@ KeWaitForSingleObject(PVOID Object,
 
         /* Block the Thread */
         DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
-        PsBlockThread(&Status, 
+        KiBlockThread(&Status, 
                       Alertable, 
                       WaitMode, 
                       (UCHAR)WaitReason);
@@ -575,7 +575,7 @@ KeWaitForMultipleObjects(ULONG Count,
 
         /* Block the Thread */
         DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
-        PsBlockThread(&Status, 
+        KiBlockThread(&Status, 
                       Alertable, 
                       WaitMode,
                       (UCHAR)WaitReason);
@@ -756,7 +756,7 @@ KiAbortWaitThread(PKTHREAD Thread,
 
     /* Reschedule the Thread */
     DPRINT("Unblocking the Thread\n");
-    PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0);
+    KiUnblockThread(Thread, &WaitStatus, 0);
 }
 
 BOOLEAN
@@ -884,7 +884,7 @@ KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
     if (!KeIsExecutingDpc() && OldIrql < DISPATCH_LEVEL && KeGetCurrentThread() != NULL && 
         KeGetCurrentThread() == KeGetCurrentPrcb()->IdleThread) {
         
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
+        KiDispatchThreadNoLock(THREAD_STATE_READY);
         KeLowerIrql(OldIrql);
         
     } else {
index b8dd343..a8acfd2 100644 (file)
 
 /* FUNCTIONS ***************************************************************/
 
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process)
+{
+    ObDeleteHandleTable(Process);
+}
 
 VOID
 ObpDecrementHandleCount(PVOID ObjectBody)
index f311cd3..73787b5 100644 (file)
@@ -128,6 +128,69 @@ PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object)
   return NULL;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
+                          OUT PEPROCESS *Process OPTIONAL,
+                          OUT PETHREAD *Thread)
+{
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PETHREAD FoundThread;
+
+  PAGED_CODE();
+
+  ASSERT(Thread);
+  ASSERT(Cid);
+
+  CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
+  {
+    ObReferenceObject(FoundThread);
+
+    PsUnlockCidHandle(CidEntry);
+
+    if(Process != NULL)
+    {
+      *Process = FoundThread->ThreadsProcess;
+    }
+    *Thread = FoundThread;
+    return STATUS_SUCCESS;
+  }
+
+  return STATUS_INVALID_PARAMETER;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsLookupThreadByThreadId(IN HANDLE ThreadId,
+                        OUT PETHREAD *Thread)
+{
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PETHREAD FoundThread;
+
+  PAGED_CODE();
+
+  ASSERT(Thread);
+
+  CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
+  {
+    ObReferenceObject(FoundThread);
+
+    PsUnlockCidHandle(CidEntry);
+
+    *Thread = FoundThread;
+    return STATUS_SUCCESS;
+  }
+
+  return STATUS_INVALID_PARAMETER;
+}
+
 VOID
 PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry)
 {
index 7082ca5..4758532 100644 (file)
@@ -32,329 +32,10 @@ static ULONG PiThreadNotifyRoutineCount = 0;
 static PCREATE_THREAD_NOTIFY_ROUTINE
 PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
 
-/* FUNCTIONS ***************************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-PsAssignImpersonationToken(PETHREAD Thread,
-                          HANDLE TokenHandle)
-{
-   PACCESS_TOKEN Token;
-   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
-   NTSTATUS Status;
-
-   if (TokenHandle != NULL)
-     {
-       Status = ObReferenceObjectByHandle(TokenHandle,
-                                          TOKEN_IMPERSONATE,
-                                          SepTokenObjectType,
-                                          KeGetPreviousMode(),
-                                          (PVOID*)&Token,
-                                          NULL);
-       if (!NT_SUCCESS(Status))
-         {
-            return(Status);
-         }
-       ImpersonationLevel = SeTokenImpersonationLevel(Token);
-     }
-   else
-     {
-       Token = NULL;
-       ImpersonationLevel = 0;
-     }
-
-   PsImpersonateClient(Thread,
-                      Token,
-                      FALSE,
-                      FALSE,
-                      ImpersonationLevel);
-   if (Token != NULL)
-     {
-       ObDereferenceObject(Token);
-     }
-
-   return(STATUS_SUCCESS);
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-PsRevertToSelf (VOID)
-{
-    PsRevertThreadToSelf(PsGetCurrentThread());
-}
-
-/*
- * @implemented
- */
-VOID
+ULONG
 STDCALL
-PsRevertThreadToSelf(
-       IN PETHREAD Thread
-       )
-{
-  if (Thread->ActiveImpersonationInfo == TRUE)
-    {
-      ObDereferenceObject (Thread->ImpersonationInfo->Token);
-      Thread->ActiveImpersonationInfo = FALSE;
-    }
-}
-
-/*
- * @implemented
- */
-VOID STDCALL
-PsImpersonateClient (IN PETHREAD Thread,
-                    IN PACCESS_TOKEN Token,
-                    IN BOOLEAN CopyOnOpen,
-                    IN BOOLEAN EffectiveOnly,
-                    IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
-{
-  if (Token == NULL)
-    {
-      if (Thread->ActiveImpersonationInfo == TRUE)
-       {
-         Thread->ActiveImpersonationInfo = FALSE;
-         if (Thread->ImpersonationInfo->Token != NULL)
-           {
-             ObDereferenceObject (Thread->ImpersonationInfo->Token);
-           }
-       }
-      return;
-    }
-
-  if (Thread->ImpersonationInfo == NULL)
-    {
-      Thread->ImpersonationInfo = ExAllocatePool (NonPagedPool,
-                                                 sizeof(PS_IMPERSONATION_INFORMATION));
-    }
-
-  Thread->ImpersonationInfo->ImpersonationLevel = ImpersonationLevel;
-  Thread->ImpersonationInfo->CopyOnOpen = CopyOnOpen;
-  Thread->ImpersonationInfo->EffectiveOnly = EffectiveOnly;
-  Thread->ImpersonationInfo->Token = Token;
-  ObReferenceObjectByPointer (Token,
-                             0,
-                             SepTokenObjectType,
-                             KernelMode);
-  Thread->ActiveImpersonationInfo = TRUE;
-}
-
-
-PACCESS_TOKEN
-PsReferenceEffectiveToken(PETHREAD Thread,
-                         PTOKEN_TYPE TokenType,
-                         PBOOLEAN EffectiveOnly,
-                         PSECURITY_IMPERSONATION_LEVEL Level)
-{
-   PEPROCESS Process;
-   PACCESS_TOKEN Token;
-   
-   if (Thread->ActiveImpersonationInfo == FALSE)
-     {
-       Process = Thread->ThreadsProcess;
-       *TokenType = TokenPrimary;
-       *EffectiveOnly = FALSE;
-       Token = Process->Token;
-     }
-   else
-     {
-       Token = Thread->ImpersonationInfo->Token;
-       *TokenType = TokenImpersonation;
-       *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
-       *Level = Thread->ImpersonationInfo->ImpersonationLevel;
-     }
-   return(Token);
-}
-
-
-NTSTATUS STDCALL
-NtImpersonateThread(IN HANDLE ThreadHandle,
-                   IN HANDLE ThreadToImpersonateHandle,
-                   IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
-{
-  SECURITY_QUALITY_OF_SERVICE SafeServiceQoS;
-  SECURITY_CLIENT_CONTEXT ClientContext;
-  PETHREAD Thread;
-  PETHREAD ThreadToImpersonate;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
-  
-  PAGED_CODE();
-  
-  PreviousMode = ExGetPreviousMode();
-  
-  if(PreviousMode != KernelMode)
-  {
-    _SEH_TRY
-    {
-      ProbeForRead(SecurityQualityOfService,
-                   sizeof(SECURITY_QUALITY_OF_SERVICE),
-                   sizeof(ULONG));
-      SafeServiceQoS = *SecurityQualityOfService;
-      SecurityQualityOfService = &SafeServiceQoS;
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
-    
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-  }
-
-  Status = ObReferenceObjectByHandle(ThreadHandle,
-                                    THREAD_IMPERSONATE,
-                                    PsThreadType,
-                                    PreviousMode,
-                                    (PVOID*)&Thread,
-                                    NULL);
-  if(NT_SUCCESS(Status))
-  {
-    Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
-                                      THREAD_DIRECT_IMPERSONATION,
-                                      PsThreadType,
-                                      PreviousMode,
-                                      (PVOID*)&ThreadToImpersonate,
-                                      NULL);
-    if(NT_SUCCESS(Status))
-    {
-      Status = SeCreateClientSecurity(ThreadToImpersonate,
-                                     SecurityQualityOfService,
-                                     0,
-                                    &ClientContext);
-      if(NT_SUCCESS(Status))
-      {
-        SeImpersonateClient(&ClientContext,
-                           Thread);
-        if(ClientContext.ClientToken != NULL)
-        {
-          ObDereferenceObject (ClientContext.ClientToken);
-        }
-      }
-
-      ObDereferenceObject(ThreadToImpersonate);
-    }
-    ObDereferenceObject(Thread);
-  }
-
-  return Status;
-}
-
-/*
- * @implemented
- */
-PACCESS_TOKEN STDCALL
-PsReferenceImpersonationToken(IN PETHREAD Thread,
-                             OUT PBOOLEAN CopyOnOpen,
-                             OUT PBOOLEAN EffectiveOnly,
-                             OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
-{
-  if (Thread->ActiveImpersonationInfo == FALSE)
-    {
-      return NULL;
-    }
-
-  *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
-  *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
-  *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
-  ObReferenceObjectByPointer (Thread->ImpersonationInfo->Token,
-                             TOKEN_ALL_ACCESS,
-                             SepTokenObjectType,
-                             KernelMode);
-
-  return Thread->ImpersonationInfo->Token;
-}
-
-#ifdef PsDereferencePrimaryToken
-#undef PsDereferenceImpersonationToken
-#endif
-/*
- * @implemented
- */
-VOID
-STDCALL
-PsDereferenceImpersonationToken(
-    IN PACCESS_TOKEN ImpersonationToken
-    )
-{
-    if (ImpersonationToken) {
-        ObDereferenceObject(ImpersonationToken);
-    }
-}
-
-#ifdef PsDereferencePrimaryToken
-#undef PsDereferencePrimaryToken
-#endif
-/*
- * @implemented
- */
-VOID
-STDCALL
-PsDereferencePrimaryToken(
-    IN PACCESS_TOKEN PrimaryToken
-    )
-{
-    ObDereferenceObject(PrimaryToken);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-STDCALL
-PsDisableImpersonation(
-    IN PETHREAD Thread,
-    IN PSE_IMPERSONATION_STATE ImpersonationState
-    )
-{
-   if (Thread->ActiveImpersonationInfo == FALSE)
-   {
-      ImpersonationState->Token = NULL;
-      ImpersonationState->CopyOnOpen = FALSE;
-      ImpersonationState->EffectiveOnly = FALSE;
-      ImpersonationState->Level = 0;
-      return TRUE;
-   }
-
-/* FIXME */
-/*   ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
-
-   Thread->ActiveImpersonationInfo = FALSE;
-   ImpersonationState->Token = Thread->ImpersonationInfo->Token;
-   ImpersonationState->CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
-   ImpersonationState->EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
-   ImpersonationState->Level = Thread->ImpersonationInfo->ImpersonationLevel;
-
-/* FIXME */
-/*   ExfReleasePushLock(&Thread->ThreadLock); */
-
-   return TRUE;
-}
-
-/*
- * @implemented
- */                       
-VOID
-STDCALL
-PsRestoreImpersonation(
-       IN PETHREAD      Thread,
-       IN PSE_IMPERSONATION_STATE      ImpersonationState
-       )
-{
-   PsImpersonateClient(Thread, ImpersonationState->Token,
-                       ImpersonationState->CopyOnOpen,
-                       ImpersonationState->EffectiveOnly,
-                       ImpersonationState->Level);
-   ObfDereferenceObject(ImpersonationState->Token);
-}
+KeSuspendThread(PKTHREAD Thread);
+/* FUNCTIONS ***************************************************************/
 
 VOID
 PiBeforeBeginThread(CONTEXT c)
@@ -362,39 +43,6 @@ PiBeforeBeginThread(CONTEXT c)
    KeLowerIrql(PASSIVE_LEVEL);
 }
 
-
-VOID STDCALL
-PiDeleteThread(PVOID ObjectBody)
-{
-  PETHREAD Thread;
-  PEPROCESS Process;
-
-  Thread = (PETHREAD)ObjectBody;
-
-  DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
-
-  Process = Thread->ThreadsProcess;
-  Thread->ThreadsProcess = NULL;
-
-  if(Thread->Cid.UniqueThread != NULL)
-  {
-    PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
-  }
-  
-  if(Thread->Tcb.Win32Thread != NULL)
-  {
-    /* Free the W32THREAD structure if present */
-    ExFreePool (Thread->Tcb.Win32Thread);
-  }
-
-  KeReleaseThread(ETHREAD_TO_KTHREAD(Thread));
-  
-  ObDereferenceObject(Process);
-  
-  DPRINT("PiDeleteThread() finished\n");
-}
-
-
 NTSTATUS
 PsInitializeThread(PEPROCESS Process,
                   PETHREAD* ThreadPtr,
@@ -446,6 +94,7 @@ PsInitializeThread(PEPROCESS Process,
 
    KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
    InitializeListHead(&Thread->TerminationPortList);
+   InitializeListHead(&Thread->ActiveTimerListHead);
    KeInitializeSpinLock(&Thread->ActiveTimerListLock);
    InitializeListHead(&Thread->IrpList);
    Thread->DeadThread = FALSE;
@@ -784,7 +433,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
    */
   if (CreateSuspended)
     {
-      PsSuspendThread(Thread, NULL);
+      KeSuspendThread(&Thread->Tcb);
     }
 
   /*
@@ -806,7 +455,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
   Thread->Tcb.Alerted[KernelMode] = TRUE;
 
   oldIrql = KeAcquireDispatcherDatabaseLock ();
-  PsUnblockThread(Thread, NULL, 0);
+  KiUnblockThread(&Thread->Tcb, NULL, 0);
   KeReleaseDispatcherDatabaseLock(oldIrql);
 
   Status = ObInsertObject((PVOID)Thread,
@@ -883,6 +532,9 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
        return(Status);
      }
 
+    /* Set the thread as a system thread */
+    Thread->SystemThread = TRUE;
+     
    Status = PsCreateCidHandle(Thread,
                               PsThreadType,
                               &Thread->Cid.UniqueThread);
@@ -906,7 +558,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
      }
 
    oldIrql = KeAcquireDispatcherDatabaseLock ();
-   PsUnblockThread(Thread, NULL, 0);
+   KiUnblockThread(&Thread->Tcb, NULL, 0);
    KeReleaseDispatcherDatabaseLock(oldIrql);
    
    Status = ObInsertObject((PVOID)Thread,
index a028cdb..a901562 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ps/debug.c
@@ -9,13 +8,6 @@
  *                  Phillip Susi
  */
 
-/*
- * NOTE:
- * 
- * All of the routines that manipulate the thread queue synchronize on
- * a single spinlock
- * 
- */
 
 /* INCLUDES ****************************************************************/
 
 #define NDEBUG
 #include <internal/debug.h>
 
-/* FUNCTIONS ***************************************************************/
+/* GLOBALS *****************************************************************/
 
-VOID
-KeContextToTrapFrame(PCONTEXT Context,
-                    PKTRAP_FRAME TrapFrame)
-{
-   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
-     {
-       TrapFrame->Esp = Context->Esp;
-       TrapFrame->Ss = Context->SegSs;
-       TrapFrame->Cs = Context->SegCs;
-       TrapFrame->Eip = Context->Eip;
-       TrapFrame->Eflags = Context->EFlags;    
-       TrapFrame->Ebp = Context->Ebp;
-     }
-   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
-     {
-       TrapFrame->Eax = Context->Eax;
-       TrapFrame->Ebx = Context->Ebx;
-       TrapFrame->Ecx = Context->Ecx;
-       TrapFrame->Edx = Context->Edx;
-       TrapFrame->Esi = Context->Esi;
-       TrapFrame->Edi = Context->Edi;
-     }
-   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
-     {
-       TrapFrame->Ds = Context->SegDs;
-       TrapFrame->Es = Context->SegEs;
-       TrapFrame->Fs = Context->SegFs;
-       TrapFrame->Gs = Context->SegGs;
-     }
-   if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
-     {
-       /*
-        * Not handled
-        *
-        * This should be handled separately I think.
-        *  - blight
-        */
-     }
-   if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
-     {
-       /*
-        * Not handled
-        */
-     }
-}
-
-VOID
-KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
-                    PCONTEXT Context)
-{
-   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
-     {
-       Context->SegSs = TrapFrame->Ss;
-       Context->Esp = TrapFrame->Esp;
-       Context->SegCs = TrapFrame->Cs;
-       Context->Eip = TrapFrame->Eip;
-       Context->EFlags = TrapFrame->Eflags;
-       Context->Ebp = TrapFrame->Ebp;
-     }
-   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
-     {
-       Context->Eax = TrapFrame->Eax;
-       Context->Ebx = TrapFrame->Ebx;
-       Context->Ecx = TrapFrame->Ecx;
-       /*
-        * NOTE: In the trap frame which is built on entry to a system
-        * call TrapFrame->Edx will actually hold the address of the
-        * previous TrapFrame. I don't believe leaking this information
-        * has security implications. Also EDX holds the address of the
-        * arguments to the system call in progress so it isn't of much
-        * interest to the debugger.
-        */
-       Context->Edx = TrapFrame->Edx;
-       Context->Esi = TrapFrame->Esi;
-       Context->Edi = TrapFrame->Edi;
-     }
-   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
-     {
-       Context->SegDs = TrapFrame->Ds;
-       Context->SegEs = TrapFrame->Es;
-       Context->SegFs = TrapFrame->Fs;
-       Context->SegGs = TrapFrame->Gs;
-     }
-   if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
-     {
-       /*
-        * FIXME: Implement this case
-        */     
-       Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
-     }
-   if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
-     {
-       /*
-        * FIXME: Implement this case
-        *
-        * I think this should only be filled for FPU exceptions, otherwise I
-         * would not know where to get it from as it can be the current state
-        * of the FPU or already saved in the thread's FPU save area.
-        *  -blight
-        */
-       Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
-     }
-#if 0
-   if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
-     {
-       /*
-        * FIXME: Investigate this
-        *
-        * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
-        * This should only be filled in case of a SIMD exception I think, so
-        * this is not the right place (like for FPU the state could already be
-        * saved in the thread's FX_SAVE_AREA or still be in the CPU)
-        *  -blight
-        */
-        Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
-     }
-#endif
-}
+/* Thread "Set/Get Context" Context Structure */
+typedef struct _GET_SET_CTX_CONTEXT {
+    KAPC Apc;
+    KEVENT Event;
+    CONTEXT Context;
+} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
 
-VOID STDCALL
-KeGetSetContextRundownRoutine(PKAPC Apc)
-{
-  PKEVENT Event;
-  PNTSTATUS Status;
 
-  Event = (PKEVENT)Apc->SystemArgument1;   
-  Status = (PNTSTATUS)Apc->SystemArgument2;
-  (*Status) = STATUS_THREAD_IS_TERMINATING;
-  KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
-}
+/* FUNCTIONS ***************************************************************/
 
-VOID STDCALL
-KeGetContextKernelRoutine(PKAPC Apc,
-                         PKNORMAL_ROUTINE* NormalRoutine,
-                         PVOID* NormalContext,
-                         PVOID* SystemArgument1,
-                         PVOID* SystemArgument2)
 /*
  * FUNCTION: This routine is called by an APC sent by NtGetContextThread to
  * copy the context of a thread into a buffer.
  */
+VOID 
+STDCALL
+PspGetOrSetContextKernelRoutine(PKAPC Apc,
+                                PKNORMAL_ROUTINE* NormalRoutine,
+                                PVOID* NormalContext,
+                                PVOID* SystemArgument1,
+                                PVOID* SystemArgument2)
 {
-  PKEVENT Event;
-  PCONTEXT Context;
-  PNTSTATUS Status;
-   
-  Context = (PCONTEXT)(*NormalContext);
-  Event = (PKEVENT)(*SystemArgument1);
-  Status = (PNTSTATUS)(*SystemArgument2);
+    PGET_SET_CTX_CONTEXT GetSetContext;
+    PKEVENT Event;
+    PCONTEXT Context;
    
-  KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
+    /* Get the Context Structure */
+    GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
+    Context = &GetSetContext->Context;
+    Event = &GetSetContext->Event;
+
+    /* Check if it's a set or get */
+    if (SystemArgument1) {
+        
+        /* Get the Context */ 
+        KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
+        
+    } else {
+        
+        /* Set the Context */
+        KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
+    }
    
-  *Status = STATUS_SUCCESS;
-  KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+    /* Notify the Native API that we are done */
+    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
 }
 
-NTSTATUS STDCALL
+NTSTATUS 
+STDCALL
 NtGetContextThread(IN HANDLE ThreadHandle,
-                  OUT PCONTEXT ThreadContext)
+                   OUT PCONTEXT ThreadContext)
 {
-  PETHREAD Thread;
-  CONTEXT Context;
-  KAPC Apc;
-  KEVENT Event;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
-  
-  PAGED_CODE();
+    PETHREAD Thread;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    GET_SET_CTX_CONTEXT GetSetContext;
+    NTSTATUS Status = STATUS_SUCCESS;
   
-  PreviousMode = ExGetPreviousMode();
+    PAGED_CODE();
 
-  if(PreviousMode != KernelMode)
-  {
-    _SEH_TRY
-    {
-      ProbeForWrite(ThreadContext,
-                    sizeof(CONTEXT),
-                    sizeof(ULONG));
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
+    /* Check the buffer to be OK */
+    if(PreviousMode != KernelMode) {
+    
+        _SEH_TRY {
+            
+            ProbeForWrite(ThreadContext,
+                          sizeof(CONTEXT),
+                          sizeof(ULONG));
+        } _SEH_HANDLE {
+            
+            Status = _SEH_GetExceptionCode();
+            
+        } _SEH_END;
 
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
+        if(!NT_SUCCESS(Status)) return Status;
     }
-  }
   
-  Status = ObReferenceObjectByHandle(ThreadHandle,
-                                     THREAD_GET_CONTEXT,
-                                     PsThreadType,
-                                     PreviousMode,
-                                     (PVOID*)&Thread,
-                                     NULL);
-  if(NT_SUCCESS(Status))
-  {
-    if(Thread == PsGetCurrentThread())
-    {
-      /*
-       * I don't know if trying to get your own context makes much
-       * sense but we can handle it more efficently.
-       */
-       
-      KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context);
-    }
-    else
-    {
-      KeInitializeEvent(&Event,
-                        NotificationEvent,
-                        FALSE);
-
-      KeInitializeApc(&Apc,
-                      &Thread->Tcb,
-                      OriginalApcEnvironment,
-                      KeGetContextKernelRoutine,
-                      KeGetSetContextRundownRoutine,
-                      NULL,
-                      KernelMode,
-                      (PVOID)&Context);
-      if (!KeInsertQueueApc(&Apc,
-                           (PVOID)&Event,
-                           (PVOID)&Status,
-                           IO_NO_INCREMENT))
-       {
-         Status = STATUS_THREAD_IS_TERMINATING;
-       }
-      else
-       {
-         Status = KeWaitForSingleObject(&Event,
-                                        0,
-                                        KernelMode,
-                                        FALSE,
-                                        NULL);
-       }
-    }
-    ObDereferenceObject(Thread);
+    /* Get the Thread Object */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_GET_CONTEXT,
+                                       PsThreadType,
+                                       PreviousMode,
+                                       (PVOID*)&Thread,
+                                       NULL);
+    
+    /* Check success */
+    if(NT_SUCCESS(Status)) {
+        
+        /* Check if we're running in the same thread */
+        if(Thread == PsGetCurrentThread()) {
+      
+            /*
+             * I don't know if trying to get your own context makes much
+             * sense but we can handle it more efficently.
+             */
+            KeTrapFrameToContext(Thread->Tcb.TrapFrame, &GetSetContext.Context);
+        
+        } else {
+            
+            /* Use an APC... Initialize the Event */
+            KeInitializeEvent(&GetSetContext.Event,
+                              NotificationEvent,
+                              FALSE);
+            
+            /* Initialize the APC */
+            KeInitializeApc(&GetSetContext.Apc,
+                            &Thread->Tcb,
+                            OriginalApcEnvironment,
+                            PspGetOrSetContextKernelRoutine,
+                            NULL,
+                            NULL,
+                            KernelMode,
+                            NULL);
+            
+            /* Queue it as a Get APC */
+            if (!KeInsertQueueApc(&GetSetContext.Apc,
+                                  (PVOID)1,
+                                  NULL,
+                                  IO_NO_INCREMENT)) {
+                
+                Status = STATUS_THREAD_IS_TERMINATING;
+            
+            } else {
+            
+                /* Wait for the APC to complete */
+                Status = KeWaitForSingleObject(&GetSetContext.Event,
+                                               0,
+                                               KernelMode,
+                                               FALSE,
+                                               NULL);
+            }
+        }
+        
+        /* Dereference the thread */
+        ObDereferenceObject(Thread);
     
-    if(NT_SUCCESS(Status))
-    {
-      _SEH_TRY
-      {
-        *ThreadContext = Context;
-      }
-      _SEH_HANDLE
-      {
-        Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
+        /* Check for success and return the Context */
+        if(NT_SUCCESS(Status)) {
+      
+            _SEH_TRY {
+                
+                *ThreadContext = GetSetContext.Context;
+          
+            } _SEH_HANDLE {
+                
+                Status = _SEH_GetExceptionCode();
+            
+            } _SEH_END;          
+        }
     }
-  }
   
-  return Status;
+    /* Return status */        
+    return Status;
 }
 
-VOID STDCALL
-KeSetContextKernelRoutine(PKAPC Apc,
-                         PKNORMAL_ROUTINE* NormalRoutine,
-                         PVOID* NormalContext,
-                         PVOID* SystemArgument1,
-                         PVOID* SystemArgument2)
-/*
- * FUNCTION: This routine is called by an APC sent by NtSetContextThread to
- * set the context of a thread from a buffer.
- */
-{
-  PKEVENT Event;
-  PCONTEXT Context;
-  PNTSTATUS Status;
-   
-  Context = (PCONTEXT)(*NormalContext);
-  Event = (PKEVENT)(*SystemArgument1);
-  Status = (PNTSTATUS)(*SystemArgument2);
-   
-  KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
-   
-  *Status = STATUS_SUCCESS;
-  KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
-}
-
-NTSTATUS STDCALL
+NTSTATUS 
+STDCALL
 NtSetContextThread(IN HANDLE ThreadHandle,
-                  IN PCONTEXT ThreadContext)
+                   IN PCONTEXT ThreadContext)
 {
-  PETHREAD Thread;
-  KAPC Apc;
-  KEVENT Event;
-  CONTEXT Context;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
+    PETHREAD Thread;
+    GET_SET_CTX_CONTEXT GetSetContext;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
   
-  PAGED_CODE();
+    PAGED_CODE();
   
-  PreviousMode = ExGetPreviousMode();
-  
-  if(PreviousMode != KernelMode)
-  {
-    _SEH_TRY
-    {
-      ProbeForRead(ThreadContext,
-                   sizeof(CONTEXT),
-                   sizeof(ULONG));
-      Context = *ThreadContext;
-      ThreadContext = &Context;
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
+    /* Check the buffer to be OK */
+    if(PreviousMode != KernelMode) {
+    
+        _SEH_TRY {
+            
+            ProbeForRead(ThreadContext,
+                         sizeof(CONTEXT),
+                         sizeof(ULONG));
+            
+            GetSetContext.Context = *ThreadContext;
+            ThreadContext = &GetSetContext.Context;
+            
+        } _SEH_HANDLE {
+            
+            Status = _SEH_GetExceptionCode();
+        } _SEH_END;
     
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
+        if(!NT_SUCCESS(Status)) return Status;
     }
-  }
 
-  Status = ObReferenceObjectByHandle(ThreadHandle,
-                                     THREAD_SET_CONTEXT,
-                                     PsThreadType,
-                                     PreviousMode,
-                                     (PVOID*)&Thread,
-                                     NULL);
-  if(NT_SUCCESS(Status))
-  {
-    if (Thread == PsGetCurrentThread())
-    {
-      /*
-       * I don't know if trying to set your own context makes much
-       * sense but we can handle it more efficently.
-       */
-       
-      KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame);
-    }
-    else
-    {
-      KeInitializeEvent(&Event,
-                        NotificationEvent,
-                        FALSE);        
-       
-      KeInitializeApc(&Apc,
-                      &Thread->Tcb,
-                      OriginalApcEnvironment,
-                      KeSetContextKernelRoutine,
-                      KeGetSetContextRundownRoutine,
-                      NULL,
-                      KernelMode,
-                      (PVOID)&Context);
-      if (!KeInsertQueueApc(&Apc,
-                           (PVOID)&Event,
-                           (PVOID)&Status,
-                           IO_NO_INCREMENT))
-       {
-         Status = STATUS_THREAD_IS_TERMINATING;
-       }
-      else
-       {
-         Status = KeWaitForSingleObject(&Event,
-                                        0,
-                                        KernelMode,
-                                        FALSE,
-                                         NULL);
-       }
+    /* Get the Thread Object */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_SET_CONTEXT,
+                                       PsThreadType,
+                                       PreviousMode,
+                                       (PVOID*)&Thread,
+                                       NULL);
+    
+    /* Check success */
+    if(NT_SUCCESS(Status)) {
+        
+        /* Check if we're running in the same thread */
+        if(Thread == PsGetCurrentThread()) {
+      
+            /*
+             * I don't know if trying to get your own context makes much
+             * sense but we can handle it more efficently.
+             */
+            KeContextToTrapFrame(&GetSetContext.Context, Thread->Tcb.TrapFrame);
+        
+        } else {
+            
+            /* Use an APC... Initialize the Event */
+            KeInitializeEvent(&GetSetContext.Event,
+                              NotificationEvent,
+                              FALSE);
+            
+            /* Initialize the APC */
+            KeInitializeApc(&GetSetContext.Apc,
+                            &Thread->Tcb,
+                            OriginalApcEnvironment,
+                            PspGetOrSetContextKernelRoutine,
+                            NULL,
+                            NULL,
+                            KernelMode,
+                            NULL);
+            
+            /* Queue it as a Get APC */
+            if (!KeInsertQueueApc(&GetSetContext.Apc,
+                                  NULL,
+                                  NULL,
+                                  IO_NO_INCREMENT)) {
+                
+                Status = STATUS_THREAD_IS_TERMINATING;
+            
+            } else {
+            
+                /* Wait for the APC to complete */
+                Status = KeWaitForSingleObject(&GetSetContext.Event,
+                                               0,
+                                               KernelMode,
+                                               FALSE,
+                                               NULL);
+            }
+        }
+        
+        /* Dereference the thread */
+        ObDereferenceObject(Thread);
     }
-    ObDereferenceObject(Thread);
-  }
   
-  return Status;
+    /* Return status */        
+    return Status;
 }
 
 /* EOF */
index 430d4ac..b8d2598 100644 (file)
@@ -79,7 +79,7 @@ PsInitIdleThread(VOID)
      }
 
    oldIrql = KeAcquireDispatcherDatabaseLock ();
-   PsUnblockThread(IdleThread, NULL, 0);
+   KiUnblockThread(&IdleThread->Tcb, NULL, 0);
    KeReleaseDispatcherDatabaseLock(oldIrql);
 
    KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb;
index ea16797..5572bec 100644 (file)
@@ -1,11 +1,11 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ps/kill.c
- * PURPOSE:         Terminating a thread
+ * PURPOSE:         Thread Termination and Reaping
  * 
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 #include <internal/debug.h>
 
 /* GLOBALS *******************************************************************/
-
-VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
-NTSTATUS STDCALL NtCallTerminatePorts(PETHREAD Thread);
-
+      
 #define TAG_TERMINATE_APC   TAG('T', 'A', 'P', 'C')
 
-LIST_ENTRY ThreadsToReapHead;
-
-#define TERMINATE_PROC 0x1
-#define TERMINATE_APC  0x2
+LIST_ENTRY PspReaperListHead;
+WORK_QUEUE_ITEM PspReaperWorkItem;
+BOOLEAN PspReaping = FALSE;
+extern LIST_ENTRY PsActiveProcessHead;
+extern FAST_MUTEX PspActiveProcessMutex;
 
 /* FUNCTIONS *****************************************************************/
 
+STDCALL
 VOID
-PsInitializeThreadReaper(VOID)
+PspReapRoutine(PVOID Context)
 {
-  InitializeListHead(&ThreadsToReapHead);
+    KIRQL OldIrql;
+    PETHREAD Thread;
+    PLIST_ENTRY ListEntry;
+    /* Acquire lock */
+    DPRINT("Evil reaper running!!\n");
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+    
+    /* Loop the reap list */
+    while((ListEntry = RemoveHeadList(&PspReaperListHead)) != &PspReaperListHead) {
+        
+        /* Get the Current Thread to Terminate */
+        Thread = CONTAINING_RECORD(ListEntry, ETHREAD, TerminationPortList);
+    
+        /* Unlock the Dispatcher */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        /* Remove the Reference */
+        ObDereferenceObject(Thread);
+        
+        /* Reacquire the Lock */
+        OldIrql = KeAcquireDispatcherDatabaseLock();
+    }
+    
+    PspReaping = FALSE;
+    KeReleaseDispatcherDatabaseLock(OldIrql);
 }
 
 VOID
-PsReapThreads(VOID)
+STDCALL
+PspTerminateProcessThreads(PEPROCESS Process,
+                           NTSTATUS ExitStatus)
 {
-  KIRQL oldlvl;
-  PETHREAD Thread;
-  PLIST_ENTRY ListEntry;
-
-  oldlvl = KeAcquireDispatcherDatabaseLock();
-  while((ListEntry = RemoveHeadList(&ThreadsToReapHead)) != &ThreadsToReapHead)
-  {
-    PiNrThreadsAwaitingReaping--;
-    KeReleaseDispatcherDatabaseLock(oldlvl);
-    Thread = CONTAINING_RECORD(ListEntry, ETHREAD, TerminationPortList);
-
-    ObDereferenceObject(Thread);
-    oldlvl = KeAcquireDispatcherDatabaseLock();
-  }
-  KeReleaseDispatcherDatabaseLock(oldlvl);
+    PLIST_ENTRY CurrentEntry;
+    PETHREAD Thread, CurrentThread = PsGetCurrentThread();
+   
+    CurrentEntry = Process->ThreadListHead.Flink;
+    while (CurrentEntry != &Process->ThreadListHead) {
+       
+        /* Get the Current Thread */
+        Thread = CONTAINING_RECORD(CurrentEntry, ETHREAD, ThreadListEntry);
+        
+        /* Make sure it's not the one we're in */
+        if (Thread != CurrentThread) {
+        
+            /* Make sure it didn't already terminate */
+            if (!Thread->HasTerminated) {
+        
+                Thread->HasTerminated = TRUE;
+                /* Terminate it by APC */
+                PspTerminateThreadByPointer(Thread, ExitStatus);
+                
+                /* Unsuspend it */
+                KeForceResumeThread(&Thread->Tcb);
+            }
+        }
+        
+        /* Move to the Next Thread */
+        CurrentEntry = CurrentEntry->Flink;
+    }
 }
 
-VOID
-PsQueueThreadReap(PETHREAD Thread)
+VOID 
+STDCALL 
+PspDeleteProcess(PVOID ObjectBody)
 {
-  InsertTailList(&ThreadsToReapHead, &Thread->TerminationPortList);
-  PiNrThreadsAwaitingReaping++;
-}
+    PEPROCESS Process = (PEPROCESS)ObjectBody;
 
-VOID
-PiTerminateProcessThreads(PEPROCESS Process,
-                         NTSTATUS ExitStatus)
-{
-   KIRQL oldlvl;
-   PLIST_ENTRY current_entry;
-   PETHREAD current, CurrentThread = PsGetCurrentThread();
-   
-   DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
-         Process, ExitStatus);
-         
-   oldlvl = KeAcquireDispatcherDatabaseLock();
-   
-   current_entry = Process->ThreadListHead.Flink;
-   while (current_entry != &Process->ThreadListHead)
-     {
-       current = CONTAINING_RECORD(current_entry, ETHREAD,
-                                   ThreadListEntry);
-       if (current != CurrentThread && current->HasTerminated == 0)
-         {
-            DPRINT("Terminating %x, current thread: %x, "
-                   "thread's process: %x\n", current, PsGetCurrentThread(), 
-                   current->ThreadsProcess);
-             KeReleaseDispatcherDatabaseLock(oldlvl);
-            PsTerminateOtherThread(current, ExitStatus);
-             oldlvl = KeAcquireDispatcherDatabaseLock();
-            current_entry = Process->ThreadListHead.Flink;
-         }
-       else
-         {
-            current_entry = current_entry->Flink;
-         }
-     }
-   KeReleaseDispatcherDatabaseLock(oldlvl);
-   DPRINT("Finished PiTerminateProcessThreads()\n");
+    DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
+
+    /* Delete the CID Handle */   
+    if(Process->UniqueProcessId != NULL) {
+    
+        PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType);
+    }
+    
+    /* KDB hook */
+    KDB_DELETEPROCESS_HOOK(Process);
+    
+    /* Dereference the Token and release Memory Information */
+    ObDereferenceObject(Process->Token);
+    MmReleaseMmInfo(Process);
+    /* Delete the W32PROCESS structure if there's one associated */
+    if(Process->Win32Process != NULL) ExFreePool(Process->Win32Process);
 }
 
-VOID
-PsTerminateCurrentThread(NTSTATUS ExitStatus)
-/*
- * FUNCTION: Terminates the current thread
- */
+VOID 
+STDCALL
+PspDeleteThread(PVOID ObjectBody)
 {
-   KIRQL oldIrql;
-   PETHREAD CurrentThread;
-   PLIST_ENTRY current_entry;
-   PKMUTANT Mutant;
-   BOOLEAN Last;
-   PEPROCESS CurrentProcess;
-   SIZE_T Length = PAGE_SIZE;
-   PVOID TebBlock;
-
-   DPRINT("PsTerminateCurrentThread(ExitStatus %x)\n", ExitStatus);
+    PETHREAD Thread = (PETHREAD)ObjectBody;
+    PEPROCESS Process = Thread->ThreadsProcess;
 
-   CurrentThread = PsGetCurrentThread();
+    DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
 
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-   if (CurrentThread->HasTerminated & TERMINATE_PROC)
-   {
-      KeReleaseDispatcherDatabaseLock(oldIrql);
-      return;
-   }
-   CurrentThread->HasTerminated |= TERMINATE_PROC;
-   KeReleaseDispatcherDatabaseLock(oldIrql);
+    /* Deassociate the Process */
+    Thread->ThreadsProcess = NULL;
 
-   KeLowerIrql(PASSIVE_LEVEL);
-
-   CurrentProcess = CurrentThread->ThreadsProcess;
+    /* Delete the CID Handle */
+    if(Thread->Cid.UniqueThread != NULL) {
+        
+        PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+    }
+  
+    /* Free the W32THREAD structure if present */
+    if(Thread->Tcb.Win32Thread != NULL) ExFreePool (Thread->Tcb.Win32Thread);
 
-   /* Can't terminate a thread if it attached another process */
-   if (AttachedApcEnvironment == CurrentThread->Tcb.ApcStateIndex)
-     {
+    /* Release the Thread */
+    KeReleaseThread(ETHREAD_TO_KTHREAD(Thread)); 
+    
+    /* Dereference the Process */
+    ObDereferenceObject(Process);
+}
+              
+/*
+ * FUNCTION: Terminates the current thread
+ * See "Windows Internals" - Chapter 13, Page 50-53
+ */
+VOID
+STDCALL
+PspExitThread(NTSTATUS ExitStatus)
+{
+    PETHREAD CurrentThread;
+    BOOLEAN Last;
+    PEPROCESS CurrentProcess;
+    SIZE_T Length = PAGE_SIZE;
+    PVOID TebBlock;
+    PLIST_ENTRY CurrentEntry;
+    PTERMINATION_PORT TerminationPort;
+
+    DPRINT("PsTerminateCurrentThread(ExitStatus %x)\n", ExitStatus);
+
+    /* Get the Current Thread and Process */
+    CurrentThread = PsGetCurrentThread();
+    CurrentThread->HasTerminated = TRUE;
+    CurrentProcess = CurrentThread->ThreadsProcess;
+
+    /* Can't terminate a thread if it attached another process */
+    if (KeIsAttachedProcess()) {
+        
         KEBUGCHECKEX(INVALID_PROCESS_ATTACH_ATTEMPT, (ULONG) CurrentProcess,
                      (ULONG) CurrentThread->Tcb.ApcState.Process,
                      (ULONG) CurrentThread->Tcb.ApcStateIndex,
                      (ULONG) CurrentThread);
-     }
-
-   KeCancelTimer(&CurrentThread->Tcb.Timer);
-
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-
-   DPRINT("terminating %x\n",CurrentThread);
-
-   CurrentThread->ExitStatus = ExitStatus;
-   KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
-
-   /* If the ProcessoR Control Block's NpxThread points to the current thread
-    * unset it.
-    */
-   InterlockedCompareExchangePointer(&KeGetCurrentPrcb()->NpxThread,
-                                     NULL, ETHREAD_TO_KTHREAD(CurrentThread));
-
-   KeReleaseDispatcherDatabaseLock(oldIrql);
-   PsLockProcess(CurrentProcess, FALSE);
-
-   /* Cancel I/O for the thread. */
-   IoCancelThreadIo(CurrentThread);
-
-   /* Remove the thread from the thread list of its process */
-   RemoveEntryList(&CurrentThread->ThreadListEntry);
-   Last = IsListEmpty(&CurrentProcess->ThreadListHead);
-   PsUnlockProcess(CurrentProcess);
-
-   /* Notify subsystems of the thread termination */
-   PspRunCreateThreadNotifyRoutines(CurrentThread, FALSE);
-   PsTerminateWin32Thread(CurrentThread);
-
-   /* Free the TEB */
-   if(CurrentThread->Tcb.Teb)
-   {
-     DPRINT("Decommit teb at %p\n", CurrentThread->Tcb.Teb);
-     ExAcquireFastMutex(&CurrentProcess->TebLock);
-     TebBlock = MM_ROUND_DOWN(CurrentThread->Tcb.Teb, MM_VIRTMEM_GRANULARITY);
-     ZwFreeVirtualMemory(NtCurrentProcess(),
-                         (PVOID *)&CurrentThread->Tcb.Teb,
-                         &Length,
-                         MEM_DECOMMIT);
-     DPRINT("teb %p, TebBlock %p\n", CurrentThread->Tcb.Teb, TebBlock);
-     if (TebBlock != CurrentProcess->TebBlock ||
-         CurrentProcess->TebBlock == CurrentProcess->TebLastAllocated)
-       {
-         MmLockAddressSpace(&CurrentProcess->AddressSpace);
-         MmReleaseMemoryAreaIfDecommitted(CurrentProcess, &CurrentProcess->AddressSpace, TebBlock);
-         MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
-       }
-     CurrentThread->Tcb.Teb = NULL;
-     ExReleaseFastMutex(&CurrentProcess->TebLock);
-   }
+    }
+    
+    /* Lower to Passive Level */
+    KeLowerIrql(PASSIVE_LEVEL);
 
-   /* abandon all owned mutants */
-   current_entry = CurrentThread->Tcb.MutantListHead.Flink;
-   while (current_entry != &CurrentThread->Tcb.MutantListHead)
-     {
-       Mutant = CONTAINING_RECORD(current_entry, KMUTANT,
-                                  MutantListEntry);
-       KeReleaseMutant(Mutant,
-                       MUTANT_INCREMENT,
-                       TRUE,
-                       FALSE);
-       current_entry = CurrentThread->Tcb.MutantListHead.Flink;
-     }
+    /* Run Thread Notify Routines before we desintegrate the thread */
+    PspRunCreateThreadNotifyRoutines(CurrentThread, FALSE);
 
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-   CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
-   KiWaitTest(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
-   KeReleaseDispatcherDatabaseLock (oldIrql);
+    /* Lock the Process before we modify its thread entries */
+    PsLockProcess(CurrentProcess, FALSE);
 
-   /* The last thread shall close the door on exit */
-   if(Last)
-   {
-    /* save the last thread exit status */
+    /* Remove the thread from the thread list of its process */
+    RemoveEntryList(&CurrentThread->ThreadListEntry);
+    Last = IsListEmpty(&CurrentProcess->ThreadListHead);
+    
+    /* Set the last Thread Exit Status */
     CurrentProcess->LastThreadExitStatus = ExitStatus;
     
-    PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
-    PsTerminateWin32Process(CurrentProcess);
+    /* Unlock the Process */
+    PsUnlockProcess(CurrentProcess);
     
-    PiTerminateProcess(CurrentProcess, ExitStatus);
-   }
-
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-
-#ifdef _ENABLE_THRDEVTPAIR
-   ExpSwapThreadEventPair(CurrentThread, NULL); /* Release the associated eventpair object, if there was one */
-#endif /* _ENABLE_THRDEVTPAIR */
-   PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
-   DPRINT1("Unexpected return, CurrentThread %x PsGetCurrentThread() %x\n", CurrentThread, PsGetCurrentThread());
-   KEBUGCHECK(0);
-}
+    /* Check if the process has a debug port */
+    if (CurrentProcess->DebugPort) {
+    
+        /* Notify the Debug API. TODO */
+        //Last ? DbgkExitProcess(ExitStatus) : DbgkExitThread(ExitStatus);
+    }
+    
+    /* Process the Termination Ports */  
+    while ((CurrentEntry = RemoveHeadList(&CurrentThread->TerminationPortList)) != 
+                           &CurrentThread->TerminationPortList) {
+        
+        /* Get the Termination Port */
+        TerminationPort = CONTAINING_RECORD(CurrentEntry,
+                                            TERMINATION_PORT,
+                                            Links);
+        
+        /* Send the LPC Message */
+        LpcSendTerminationPort(TerminationPort->Port, CurrentThread->CreateTime);
+        
+        /* Free the Port */
+        ExFreePool(TerminationPort);
+    }
+      
+    /* Rundown Win32 Structures */
+    PsTerminateWin32Thread(CurrentThread);
+    if (Last) PsTerminateWin32Process(CurrentProcess);
+   
+    /* Cancel I/O for the thread. */
+    IoCancelThreadIo(CurrentThread);
+   
+    /* Rundown Timers */
+    ExTimerRundown();
+    KeCancelTimer(&CurrentThread->Tcb.Timer);
+   
+    /* Rundown Registry Notifications. TODO (refers to NtChangeNotify, not Cm callbacks) */
+    //CmNotifyRunDown(CurrentThread);
+   
+    /* Rundown Mutexes */
+    KeRundownThread();
+     
+    /* Free the TEB */
+    if(CurrentThread->Tcb.Teb) {
+        
+        DPRINT("Decommit teb at %p\n", CurrentThread->Tcb.Teb);
+        ExAcquireFastMutex(&CurrentProcess->TebLock);
+        TebBlock = MM_ROUND_DOWN(CurrentThread->Tcb.Teb, MM_VIRTMEM_GRANULARITY);
+     
+        ZwFreeVirtualMemory(NtCurrentProcess(),
+                           (PVOID *)&CurrentThread->Tcb.Teb,
+                           &Length,
+                           MEM_DECOMMIT);
+        
+        DPRINT("teb %p, TebBlock %p\n", CurrentThread->Tcb.Teb, TebBlock);
+     
+        if (TebBlock != CurrentProcess->TebBlock ||
+            CurrentProcess->TebBlock == CurrentProcess->TebLastAllocated) {
+            
+            MmLockAddressSpace(&CurrentProcess->AddressSpace);
+            MmReleaseMemoryAreaIfDecommitted(CurrentProcess, &CurrentProcess->AddressSpace, TebBlock);
+            MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
+        }
+    
+        CurrentThread->Tcb.Teb = NULL;
+        ExReleaseFastMutex(&CurrentProcess->TebLock);
+    }
+   
+    /* Set the Exit Status and Exit Time */
+    CurrentThread->ExitStatus = ExitStatus;
+    KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
+       
+    /* If the Processor Control Block's NpxThread points to the current thread
+     * unset it.
+     */
+    InterlockedCompareExchangePointer(&KeGetCurrentPrcb()->NpxThread,
+                                      NULL,
+                                      (PKPROCESS)CurrentThread);
+   
+    /* The last Thread shuts down the Process */
+    if (Last) PspExitProcess(CurrentProcess);
 
-VOID STDCALL
-PiTerminateThreadRundownRoutine(PKAPC Apc)
-{
-  ExFreePool(Apc);
+    /* Terminate the Thread from the Scheduler */
+    KeTerminateThread(0);
+    DPRINT1("Unexpected return, CurrentThread %x PsGetCurrentThread() %x\n", CurrentThread, PsGetCurrentThread());
+    KEBUGCHECK(0);
 }
 
-VOID STDCALL
-PiTerminateThreadKernelRoutine(PKAPC Apc,
-                              PKNORMAL_ROUTINE* NormalRoutine,
-                              PVOID* NormalContext,
-                              PVOID* SystemArgument1,
-                              PVOID* SystemArguemnt2)
+VOID 
+STDCALL
+PsExitSpecialApc(PKAPC Apc,
+                 PKNORMAL_ROUTINE* NormalRoutine,
+                 PVOID* NormalContext,
+                 PVOID* SystemArgument1,
+                 PVOID* SystemArguemnt2)
 {
-  ExFreePool(Apc);
+    NTSTATUS ExitStatus = (NTSTATUS)Apc->NormalContext;
+    
+    /* Free the APC */
+    ExFreePool(Apc);
+    
+    /* Terminate the Thread */
+    PspExitThread(ExitStatus);
 }
 
-VOID STDCALL
-PiTerminateThreadNormalRoutine(PVOID NormalContext,
-                            PVOID SystemArgument1,
-                            PVOID SystemArgument2)
+VOID 
+STDCALL
+PspExitNormalApc(PVOID NormalContext,
+                 PVOID SystemArgument1,
+                 PVOID SystemArgument2)
 {
-  PsTerminateCurrentThread((NTSTATUS)SystemArgument1);
+    /* Not fully supported yet... must work out some issues that 
+     * I don't understand yet -- Alex 
+     */
+    DPRINT1("APC2\n");
+    PspExitThread((NTSTATUS)NormalContext);
 }
 
-VOID
-PsTerminateOtherThread(PETHREAD Thread,
-                      NTSTATUS ExitStatus)
 /*
- * FUNCTION: Terminate a thread when calling from another thread's context
- * NOTES: This function must be called with PiThreadLock held
+ * See "Windows Internals" - Chapter 13, Page 49
  */
+VOID
+STDCALL
+PspTerminateThreadByPointer(PETHREAD Thread,
+                            NTSTATUS ExitStatus)
 {
-  PKAPC Apc;
-  KIRQL OldIrql;
-
-  DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
-        Thread, ExitStatus);
-
-  OldIrql = KeAcquireDispatcherDatabaseLock();
-  if (Thread->HasTerminated & TERMINATE_APC)
-  {
-     KeReleaseDispatcherDatabaseLock (OldIrql);
-     return;
-  }
-  Thread->HasTerminated |= TERMINATE_APC;
-  KeReleaseDispatcherDatabaseLock (OldIrql);
-  Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
-  KeInitializeApc(Apc,
-                 &Thread->Tcb,
-                 OriginalApcEnvironment,
-                 PiTerminateThreadKernelRoutine,
-                 PiTerminateThreadRundownRoutine,
-                 PiTerminateThreadNormalRoutine,
-                 KernelMode,
-                 NULL);
-  KeInsertQueueApc(Apc,
-                  (PVOID)ExitStatus,
-                  NULL,
-                  IO_NO_INCREMENT);
-
-  OldIrql = KeAcquireDispatcherDatabaseLock();          
-  if (THREAD_STATE_BLOCKED == Thread->Tcb.State && UserMode == Thread->Tcb.WaitMode)
-    {
-      DPRINT("Unblocking thread\n");
-      KiAbortWaitThread((PKTHREAD)Thread, STATUS_THREAD_IS_TERMINATING, IO_NO_INCREMENT);
+    PKAPC Apc;  
+    
+    DPRINT("PspTerminatedThreadByPointer(Thread %x, ExitStatus %x)\n",
+            Thread, ExitStatus);
+    
+    /* Check if we are already in the right context */
+    if (PsGetCurrentThread() == Thread) {
+    
+        /* Directly terminate the thread */
+        PspExitThread(ExitStatus);
     }
-  KeReleaseDispatcherDatabaseLock(OldIrql); 
+    
+    /* Allocate the APC */
+    Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
+    
+    /* Initialize a Kernel Mode APC to Kill the Thread */
+    KeInitializeApc(Apc,
+                    &Thread->Tcb,
+                    OriginalApcEnvironment,
+                    PsExitSpecialApc,
+                    NULL,
+                    PspExitNormalApc,
+                    KernelMode,
+                    (PVOID)ExitStatus);
+    
+    /* Insert it into the APC Queue */
+    KeInsertQueueApc(Apc,
+                     Apc,
+                     NULL,
+                     2);
+    
+    /* Forcefully resume the thread */
+    KeForceResumeThread(&Thread->Tcb);
 }
-
-NTSTATUS STDCALL
-PiTerminateProcess(PEPROCESS Process,
-                  NTSTATUS ExitStatus)
-{
-   KIRQL OldIrql;
-   PEPROCESS CurrentProcess;
-
-   DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n",
-          Process, ExitStatus, ObGetObjectPointerCount(Process),
-          ObGetObjectHandleCount(Process));
-   
-   ObReferenceObject(Process);
-   if (Process->Pcb.State == PROCESS_STATE_TERMINATED)
-     {
-        ObDereferenceObject(Process);
-       return(STATUS_SUCCESS);
-     }
-
-   Process->Pcb.State = PROCESS_STATE_TERMINATED;
    
-   CurrentProcess = PsGetCurrentProcess();
-   if (Process != CurrentProcess)
-   {
-      KeAttachProcess(&Process->Pcb);
-   }
-
-   ObDeleteHandleTable(Process);
-   if (Process != CurrentProcess)
-   {
-      KeDetachProcess();
-   }
-   OldIrql = KeAcquireDispatcherDatabaseLock ();
-   Process->Pcb.DispatcherHeader.SignalState = TRUE;
-   KiWaitTest(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
-   KeReleaseDispatcherDatabaseLock (OldIrql);
-   ObDereferenceObject(Process);
-   return(STATUS_SUCCESS);
+NTSTATUS 
+STDCALL
+PspExitProcess(PEPROCESS Process)
+{
+    DPRINT("PspExitProcess\n");
+           
+    PspRunCreateProcessNotifyRoutines(Process, FALSE);
+           
+    /* Remove it from the Active List */
+    ExAcquireFastMutex(&PspActiveProcessMutex);
+    RemoveEntryList(&Process->ProcessListEntry);
+    ExReleaseFastMutex(&PspActiveProcessMutex);
+    
+    ObKillProcess(Process);
+    KeSetProcess(&Process->Pcb, IO_NO_INCREMENT);
+    return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL
-NtTerminateProcess(IN  HANDLE          ProcessHandle  OPTIONAL,
-                  IN   NTSTATUS        ExitStatus)
+NTSTATUS 
+STDCALL
+NtTerminateProcess(IN HANDLE ProcessHandle  OPTIONAL,
+                   IN NTSTATUS ExitStatus)
 {
-   NTSTATUS Status;
-   PEPROCESS Process;
-   
-   PAGED_CODE();
+    NTSTATUS Status;
+    PEPROCESS Process;
    
-   DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
-          ProcessHandle, ExitStatus);
+    PAGED_CODE();
    
-   Status = ObReferenceObjectByHandle(ProcessHandle,
-                                      PROCESS_TERMINATE,
-                                      PsProcessType,
-                                     KeGetCurrentThread()->PreviousMode,
-                                      (PVOID*)&Process,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-   Process->ExitStatus = ExitStatus;
-   PiTerminateProcessThreads(Process, ExitStatus);
-   if (PsGetCurrentThread()->ThreadsProcess == Process)
-     {
-       ObDereferenceObject(Process);
-       PsTerminateCurrentThread(ExitStatus);
-       /*
-        * We should never get here!
-        */
-       return(STATUS_SUCCESS);
-     }
-   ObDereferenceObject(Process);
-   return(STATUS_SUCCESS);
+    DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
+            ProcessHandle, ExitStatus);
+    
+    /* Get the Process Object */
+    Status = ObReferenceObjectByHandle(ProcessHandle,
+                                       PROCESS_TERMINATE,
+                                       PsProcessType,
+                                       KeGetPreviousMode(),
+                                       (PVOID*)&Process,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) {
+    
+        DPRINT1("Invalid handle to Process\n");
+        return(Status);
+    }
+    
+    if(Process->ExitTime.QuadPart) {
+        
+        DPRINT1("Process has an exit time!\n");
+        KeLeaveCriticalRegion();
+        return STATUS_PROCESS_IS_TERMINATING;
+    }
+    
+    /* Terminate all the Process's Threads */
+    PspTerminateProcessThreads(Process, ExitStatus);
+
+    /* Save the Exit Time */
+    KeQuerySystemTime(&Process->ExitTime);
+            
+    /* Only master thread remains... kill it off */
+    if (PsGetCurrentThread()->ThreadsProcess == Process) {
+        
+        /* Unlock and dereference */
+        ObDereferenceObject(Process);
+        PspExitThread(ExitStatus);
+        return(STATUS_SUCCESS);
+    }
+    
+    /* If we took this path instead, then do the same as above */ 
+    ObDereferenceObject(Process);
+    return(STATUS_SUCCESS);
 }
 
-
-NTSTATUS STDCALL
-NtTerminateThread(IN   HANDLE          ThreadHandle,
-                 IN    NTSTATUS        ExitStatus)
+NTSTATUS 
+STDCALL
+NtTerminateThread(IN HANDLE ThreadHandle,
+                  IN NTSTATUS ExitStatus)
 {
-   PETHREAD Thread;
-   NTSTATUS Status;
-   
-   PAGED_CODE();
+    PETHREAD Thread;
+    NTSTATUS Status;
    
-   Status = ObReferenceObjectByHandle(ThreadHandle,
-                                     THREAD_TERMINATE,
-                                     PsThreadType,
-                                     KeGetCurrentThread()->PreviousMode,
-                                     (PVOID*)&Thread,
-                                     NULL);
-   if (Status != STATUS_SUCCESS)
-     {
-       return(Status);
-     }
+    PAGED_CODE();
+    
+    /* Get the Thread Object */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_TERMINATE,
+                                       PsThreadType,
+                                       KeGetPreviousMode(),
+                                       (PVOID*)&Thread,
+                                       NULL);
+    if (Status != STATUS_SUCCESS) {
+        
+        DPRINT1("Could not reference thread object\n");
+        return(Status);
+    }
    
-   if (Thread == PsGetCurrentThread())
-     {
-        /* dereference the thread object before we kill our thread */
-        ObDereferenceObject(Thread);
-        PsTerminateCurrentThread(ExitStatus);
-        /*
-         * We should never get here!
-         */
-     }
-   else
-     {
-       PsTerminateOtherThread(Thread, ExitStatus);
-       ObDereferenceObject(Thread);
-     }
-   return(STATUS_SUCCESS);
+    /* Make sure this is not a system thread */
+    if (PsIsSystemThread(Thread)) {
+    
+        DPRINT1("Trying to Terminate a system thread!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+     
+    /* Check to see if we're running in the same thread */
+    if (Thread != PsGetCurrentThread())  {
+                 
+         /* This isn't our thread, check if it's terminated already */
+        if (!Thread->HasTerminated) {
+         
+             /* Terminate it */
+             PspTerminateThreadByPointer(Thread, ExitStatus);
+             
+             /* Resume it */
+             KeForceResumeThread(&Thread->Tcb);
+         }
+        
+    } else {
+            
+        /* Terminate him, he's ours */
+        PspExitThread(ExitStatus);
+    }
+    
+    /* Dereference the Thread and return */
+    ObDereferenceObject(Thread);
+    return(STATUS_SUCCESS);
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS 
+STDCALL
 PsTerminateSystemThread(NTSTATUS ExitStatus)
-/*
- * FUNCTION: Terminates the current thread
- * ARGUMENTS:
- *         ExitStatus = Status to pass to the creater
- * RETURNS: Doesn't
- */
 {
-   PsTerminateCurrentThread(ExitStatus);
-   return(STATUS_SUCCESS);
-}
-
-NTSTATUS STDCALL
-NtCallTerminatePorts(PETHREAD Thread)
-{
-   KIRQL oldIrql;
-   PLIST_ENTRY current_entry;
-   PEPORT_TERMINATION_REQUEST current;
-   
-   PAGED_CODE();
-   
-   KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
-   while ((current_entry = RemoveHeadList(&Thread->TerminationPortList)) !=
-         &Thread->TerminationPortList);
-     {
-       current = CONTAINING_RECORD(current_entry,
-                                   EPORT_TERMINATION_REQUEST,
-                                   ThreadListEntry);
-       KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
-       LpcSendTerminationPort(current->Port, 
-                              Thread->CreateTime);
-       ExFreePool(current);
-       KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
-     }
-   KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
-   return(STATUS_SUCCESS);
+    PETHREAD Thread = PsGetCurrentThread();
+    
+    /* Make sure this is a system thread */
+    if (!PsIsSystemThread(Thread)) {
+    
+        DPRINT1("Trying to Terminate a non-system thread!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+        
+    /* Terminate it for real */
+    PspExitThread(ExitStatus);
+    return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL
+NTSTATUS 
+STDCALL
 NtRegisterThreadTerminatePort(HANDLE PortHandle)
 {
-   NTSTATUS Status;
-   PEPORT_TERMINATION_REQUEST Request;
-   PEPORT TerminationPort;
-   KIRQL oldIrql;
-   PETHREAD Thread;
+    NTSTATUS Status;
+    PTERMINATION_PORT TerminationPort;
+    PVOID TerminationLpcPort;
    
-   PAGED_CODE();
+    PAGED_CODE();
+    
+    /* Get the Port */
+    Status = ObReferenceObjectByHandle(PortHandle,
+                                       PORT_ALL_ACCESS,
+                                       LpcPortObjectType,
+                                       KeGetPreviousMode(),
+                                       &TerminationLpcPort,
+                                       NULL);   
+    if (!NT_SUCCESS(Status)) {
+        
+        DPRINT1("Failed to reference Port\n");
+        return(Status);
+    }
    
-   Status = ObReferenceObjectByHandle(PortHandle,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     KeGetCurrentThread()->PreviousMode,
-                                     (PVOID*)&TerminationPort,
-                                     NULL);   
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
+    /* Allocate the Port and make sure it suceeded */
+    if((TerminationPort = ExAllocatePoolWithTag(NonPagedPool, 
+                                                sizeof(PTERMINATION_PORT), 
+                                                TAG('P', 's', 'T', '=')))) {
+        
+        /* Associate the Port */
+        TerminationPort->Port = TerminationLpcPort;
+        InsertTailList(&PsGetCurrentThread()->TerminationPortList, &TerminationPort->Links);
+
+        /* Return success */
+        return(STATUS_SUCCESS);
    
-   Request = ExAllocatePool(NonPagedPool, sizeof(EPORT_TERMINATION_REQUEST));
-   if(Request != NULL)
-   {
-     Request->Port = TerminationPort;
-     Thread = PsGetCurrentThread();
-     KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
-     InsertTailList(&Thread->TerminationPortList, &Request->ThreadListEntry);
-     KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
-
-     return(STATUS_SUCCESS);
-   }
-   else
-   {
-     ObDereferenceObject(TerminationPort);
-     return(STATUS_INSUFFICIENT_RESOURCES);
-   }
+    } else {
+        
+        /* Dereference and Fail */
+        ObDereferenceObject(TerminationPort);
+        return(STATUS_INSUFFICIENT_RESOURCES);
+    }
 }
index d7d0541..5e2823c 100644 (file)
@@ -34,56 +34,6 @@ static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_
                                           STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
                                           PROCESS_ALL_ACCESS};
 
-static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
-{
-  ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION),     sizeof(ULONG), ICIF_QUERY ),                     /* ProcessBasicInformation */
-  ICI_SQ_SAME( sizeof(QUOTA_LIMITS),                  sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessQuotaLimits */
-  ICI_SQ_SAME( sizeof(IO_COUNTERS),                   sizeof(ULONG), ICIF_QUERY ),                     /* ProcessIoCounters */
-  ICI_SQ_SAME( sizeof(VM_COUNTERS),                   sizeof(ULONG), ICIF_QUERY ),                     /* ProcessVmCounters */
-  ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES),             sizeof(ULONG), ICIF_QUERY ),                     /* ProcessTimes */
-  ICI_SQ_SAME( sizeof(KPRIORITY),                     sizeof(ULONG), ICIF_SET ),                       /* ProcessBasePriority */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_SET ),                       /* ProcessRaisePriority */
-  ICI_SQ_SAME( sizeof(HANDLE),                        sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessDebugPort */
-  ICI_SQ_SAME( sizeof(HANDLE),                        sizeof(ULONG), ICIF_SET ),                       /* ProcessExceptionPort */
-  ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN),          sizeof(ULONG), ICIF_SET ),                       /* ProcessAccessToken */
-  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessLdtInformation */
-  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessLdtSize */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessDefaultHardErrorMode */
-  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessIoPortHandlers */
-  ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS),       sizeof(ULONG), ICIF_QUERY ),                     /* ProcessPooledUsageAndLimits */
-  ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION),  sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessWorkingSetWatch */
-  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessUserModeIOPL */
-  ICI_SQ_SAME( sizeof(BOOLEAN),                       sizeof(ULONG), ICIF_SET ),                       /* ProcessEnableAlignmentFaultFixup */
-  ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS),        sizeof(USHORT), ICIF_QUERY | ICIF_SET ),         /* ProcessPriorityClass */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessWx86Information */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessHandleCount */
-  ICI_SQ_SAME( sizeof(KAFFINITY),                     sizeof(ULONG), ICIF_SET ),                       /* ProcessAffinityMask */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessPriorityBoost */
-
-  ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query),                                   /* ProcessDeviceMap */
-         /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set),
-                                                /*Q*/ sizeof(ULONG),
-                                                /*S*/ sizeof(ULONG),
-                                                                     ICIF_QUERY | ICIF_SET ),
-
-  ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION),   sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessSessionInformation */
-  ICI_SQ_SAME( sizeof(BOOLEAN),                       sizeof(ULONG), ICIF_SET ),                       /* ProcessForegroundInformation */
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessWow64Information */
-  ICI_SQ_SAME( sizeof(UNICODE_STRING),                sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */
-
-  /* FIXME */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessLUIDDeviceMapsEnabled */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessBreakOnTermination */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessDebugObjectHandle */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessDebugFlags */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessHandleTracing */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown33 */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown34 */
-  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown35 */
-  
-  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY),                      /* ProcessCookie */
-};
-
 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT    8
 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT  8
 
@@ -93,26 +43,8 @@ static PLOAD_IMAGE_NOTIFY_ROUTINE
 PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
 
 
-typedef struct
-{
-    WORK_QUEUE_ITEM WorkQueueItem;
-    KEVENT Event;
-    PEPROCESS Process;
-    BOOLEAN IsWorkerQueue;
-} DEL_CONTEXT, *PDEL_CONTEXT;
-
 /* FUNCTIONS *****************************************************************/
 
-VOID
-STDCALL
-PsExitSpecialApc(PKAPC Apc, 
-                PKNORMAL_ROUTINE *NormalRoutine,
-                PVOID *NormalContext,
-                PVOID *SystemArgument1,
-                PVOID *SystemArgument2)
-{
-}
-
 PEPROCESS
 PsGetNextProcess(PEPROCESS OldProcess)
 {
@@ -175,130 +107,6 @@ PsGetNextProcess(PEPROCESS OldProcess)
    return(NextProcess);
 }
 
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL 
-NtOpenProcessToken(IN  HANDLE          ProcessHandle,
-                  IN   ACCESS_MASK     DesiredAccess,
-                  OUT  PHANDLE         TokenHandle)
-{
-  return NtOpenProcessTokenEx(ProcessHandle,
-                              DesiredAccess,
-                              0,
-                              TokenHandle);
-}
-
-
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-NtOpenProcessTokenEx(
-    IN HANDLE ProcessHandle,
-    IN ACCESS_MASK DesiredAccess,
-    IN ULONG HandleAttributes,
-    OUT PHANDLE TokenHandle
-    )
-{
-   PACCESS_TOKEN Token;
-   HANDLE hToken;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   PAGED_CODE();
-   
-   PreviousMode = ExGetPreviousMode();
-   
-   if(PreviousMode == UserMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForWrite(TokenHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
-
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
-
-   Status = PsOpenTokenOfProcess(ProcessHandle,
-                                &Token);
-   if(NT_SUCCESS(Status))
-   {
-     Status = ObCreateHandle(PsGetCurrentProcess(),
-                            Token,
-                            DesiredAccess,
-                            FALSE,
-                            &hToken);
-     ObDereferenceObject(Token);
-
-     if (NT_SUCCESS(Status))
-     {
-
-       _SEH_TRY
-       {
-         *TokenHandle = hToken;
-       }
-       _SEH_HANDLE
-       {
-         Status = _SEH_GetExceptionCode();
-       }
-       _SEH_END;
-     }
-   }
-   
-   return Status;
-}
-
-
-/*
- * @implemented
- */
-PACCESS_TOKEN STDCALL
-PsReferencePrimaryToken(PEPROCESS Process)
-{
-   ObReferenceObjectByPointer(Process->Token,
-                             TOKEN_ALL_ACCESS,
-                             SepTokenObjectType,
-                             KernelMode);
-   return(Process->Token);
-}
-
-
-NTSTATUS
-PsOpenTokenOfProcess(HANDLE ProcessHandle,
-                    PACCESS_TOKEN* Token)
-{
-   PEPROCESS Process;
-   NTSTATUS Status;
-   
-   Status = ObReferenceObjectByHandle(ProcessHandle,
-                                     PROCESS_QUERY_INFORMATION,
-                                     PsProcessType,
-                                     ExGetPreviousMode(),
-                                     (PVOID*)&Process,
-                                     NULL);
-   if(NT_SUCCESS(Status))
-   {
-     *Token = PsReferencePrimaryToken(Process);
-     ObDereferenceObject(Process);
-   }
-   
-   return Status;
-}
-
-
 VOID 
 PiKillMostProcesses(VOID)
 {
@@ -317,14 +125,13 @@ PiKillMostProcesses(VOID)
        if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
            current->UniqueProcessId != PsGetCurrentProcessId())
          {
-            PiTerminateProcessThreads(current, STATUS_SUCCESS);
+            PspTerminateProcessThreads(current, STATUS_SUCCESS);
          }
      }
    
    ExReleaseFastMutex(&PspActiveProcessMutex);
 }
 
-
 VOID INIT_FUNCTION
 PsInitProcessManagment(VOID)
 {
@@ -350,7 +157,7 @@ PsInitProcessManagment(VOID)
    PsProcessType->Dump = NULL;
    PsProcessType->Open = NULL;
    PsProcessType->Close = NULL;
-   PsProcessType->Delete = PiDeleteProcess;
+   PsProcessType->Delete = PspDeleteProcess;
    PsProcessType->Parse = NULL;
    PsProcessType->Security = NULL;
    PsProcessType->QueryName = NULL;
@@ -490,87 +297,6 @@ PspPostInitSystemProcess(VOID)
   }
 }
 
-VOID STDCALL
-PiDeleteProcessWorker(PVOID pContext)
-{
-  PDEL_CONTEXT Context;
-  PEPROCESS CurrentProcess;
-  PEPROCESS Process;
-
-  Context = (PDEL_CONTEXT)pContext;
-  Process = Context->Process;
-  CurrentProcess = PsGetCurrentProcess();
-
-  DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
-
-  if (CurrentProcess != Process)
-    {
-      KeAttachProcess(&Process->Pcb);
-    }
-
-  ExAcquireFastMutex(&PspActiveProcessMutex);
-  RemoveEntryList(&Process->ProcessListEntry);
-  ExReleaseFastMutex(&PspActiveProcessMutex);
-
-  /* KDB hook */
-  KDB_DELETEPROCESS_HOOK(Process);
-
-  ObDereferenceObject(Process->Token);
-
-  if (CurrentProcess != Process)
-    {
-      KeDetachProcess();
-    }
-
-  if(Process->UniqueProcessId != NULL)
-    {
-      PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType);
-    }
-
-  MmReleaseMmInfo(Process);
-  if (Context->IsWorkerQueue)
-    {
-      KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
-    }
-}
-
-VOID STDCALL 
-PiDeleteProcess(PVOID ObjectBody)
-{
-  DEL_CONTEXT Context;
-
-  Context.Process = (PEPROCESS)ObjectBody;
-
-  if (PsGetCurrentProcess() == Context.Process ||
-      PsGetCurrentThread()->ThreadsProcess == Context.Process)
-    {
-       KEBUGCHECK(0);
-    }
-
-  if (PsGetCurrentThread()->ThreadsProcess == PsGetCurrentProcess())
-    {
-      Context.IsWorkerQueue = FALSE;
-      PiDeleteProcessWorker(&Context);
-    }
-  else
-    {
-      Context.IsWorkerQueue = TRUE;
-      KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
-      ExInitializeWorkItem (&Context.WorkQueueItem, PiDeleteProcessWorker, &Context);
-      ExQueueWorkItem(&Context.WorkQueueItem, HyperCriticalWorkQueue);
-      if (KeReadStateEvent(&Context.Event) == 0)
-        {
-          KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
-       }
-    }
-
-  if(((PEPROCESS)ObjectBody)->Win32Process != NULL)
-  {
-    /* delete the W32PROCESS structure if there's one associated */
-    ExFreePool (((PEPROCESS)ObjectBody)->Win32Process);
-  }
-}
-
 static NTSTATUS
 PsCreatePeb(HANDLE ProcessHandle,
            PEPROCESS Process,
@@ -1382,1112 +1108,6 @@ NtOpenProcess(OUT PHANDLE          ProcessHandle,
      }
 }
 
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtQueryInformationProcess(IN  HANDLE ProcessHandle,
-                         IN  PROCESSINFOCLASS ProcessInformationClass,
-                         OUT PVOID ProcessInformation,
-                         IN  ULONG ProcessInformationLength,
-                         OUT PULONG ReturnLength  OPTIONAL)
-{
-   PEPROCESS Process;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   PAGED_CODE();
-   
-   PreviousMode = ExGetPreviousMode();
-   
-   DefaultQueryInfoBufferCheck(ProcessInformationClass,
-                               PsProcessInfoClass,
-                               ProcessInformation,
-                               ProcessInformationLength,
-                               ReturnLength,
-                               PreviousMode,
-                               &Status);
-   if(!NT_SUCCESS(Status))
-   {
-     DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
-     return Status;
-   }
-   
-   if(ProcessInformationClass != ProcessCookie)
-   {
-     Status = ObReferenceObjectByHandle(ProcessHandle,
-                                     PROCESS_QUERY_INFORMATION,
-                                     PsProcessType,
-                                     PreviousMode,
-                                     (PVOID*)&Process,
-                                     NULL);
-     if (!NT_SUCCESS(Status))
-       {
-       return(Status);
-       }
-   }
-   else if(ProcessHandle != NtCurrentProcess())
-   {
-     /* retreiving the process cookie is only allowed for the calling process
-        itself! XP only allowes NtCurrentProcess() as process handles even if a
-        real handle actually represents the current process. */
-     return STATUS_INVALID_PARAMETER;
-   }
-   
-   switch (ProcessInformationClass)
-     {
-      case ProcessBasicInformation:
-      {
-        PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
-         (PPROCESS_BASIC_INFORMATION)ProcessInformation;
-
-        _SEH_TRY
-        {
-         ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
-         ProcessBasicInformationP->PebBaseAddress = Process->Peb;
-         ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
-         ProcessBasicInformationP->UniqueProcessId =
-           Process->UniqueProcessId;
-         ProcessBasicInformationP->InheritedFromUniqueProcessId =
-           Process->InheritedFromUniqueProcessId;
-         ProcessBasicInformationP->BasePriority =
-           Process->Pcb.BasePriority;
-
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-       break;
-      }
-
-      case ProcessQuotaLimits:
-      case ProcessIoCounters:
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
-
-      case ProcessTimes:
-      {
-         PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation;
-         _SEH_TRY
-         {
-           ProcessTimeP->CreateTime = Process->CreateTime;
-            ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL;
-            ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL;
-           ProcessTimeP->ExitTime = Process->ExitTime;
-
-          if (ReturnLength)
-          {
-            *ReturnLength = sizeof(KERNEL_USER_TIMES);
-          }
-         }
-         _SEH_HANDLE
-         {
-           Status = _SEH_GetExceptionCode();
-         }
-         _SEH_END;
-        break;
-      }
-
-      case ProcessDebugPort:
-      {
-        _SEH_TRY
-        {
-          *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL);
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(HANDLE);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        break;
-      }
-      
-      case ProcessLdtInformation:
-      case ProcessWorkingSetWatch:
-      case ProcessWx86Information:
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
-
-      case ProcessHandleCount:
-      {
-       ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
-         
-       _SEH_TRY
-       {
-          *(PULONG)ProcessInformation = HandleCount;
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(ULONG);
-         }
-       }
-       _SEH_HANDLE
-       {
-          Status = _SEH_GetExceptionCode();
-       }
-       _SEH_END;
-       break;
-      }
-
-      case ProcessSessionInformation:
-      {
-        PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation;
-
-        _SEH_TRY
-        {
-          SessionInfo->SessionId = Process->SessionId;
-          if (ReturnLength)
-          {
-            *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
-          }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        break;
-      }
-      
-      case ProcessWow64Information:
-        DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
-
-      case ProcessVmCounters:
-      {
-       PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
-         
-       _SEH_TRY
-       {
-         pOut->PeakVirtualSize            = Process->PeakVirtualSize;
-         /*
-          * Here we should probably use VirtualSize.LowPart, but due to
-          * incompatibilities in current headers (no unnamed union),
-          * I opted for cast.
-          */
-         pOut->VirtualSize                = (ULONG)Process->VirtualSize.QuadPart;
-         pOut->PageFaultCount             = Process->Vm.PageFaultCount;
-         pOut->PeakWorkingSetSize         = Process->Vm.PeakWorkingSetSize;
-         pOut->WorkingSetSize             = Process->Vm.WorkingSetSize;
-         pOut->QuotaPeakPagedPoolUsage    = Process->QuotaPeakPoolUsage[0]; // TODO: Verify!
-         pOut->QuotaPagedPoolUsage        = Process->QuotaPoolUsage[0];     // TODO: Verify!
-         pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeakPoolUsage[1]; // TODO: Verify!
-         pOut->QuotaNonPagedPoolUsage     = Process->QuotaPoolUsage[1];     // TODO: Verify!
-         pOut->PagefileUsage              = Process->PagefileUsage;
-         pOut->PeakPagefileUsage          = Process->PeakPagefileUsage;
-
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(VM_COUNTERS);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-       break;
-      }
-
-      case ProcessDefaultHardErrorMode:
-      {
-       PULONG HardErrMode = (PULONG)ProcessInformation;
-       _SEH_TRY
-       {
-         *HardErrMode = Process->DefaultHardErrorProcessing;
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(ULONG);
-         }
-       }
-       _SEH_HANDLE
-       {
-          Status = _SEH_GetExceptionCode();
-       }
-       _SEH_END;
-       break;
-      }
-
-      case ProcessPriorityBoost:
-      {
-       PULONG BoostEnabled = (PULONG)ProcessInformation;
-         
-       _SEH_TRY
-       {
-         *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
-
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(ULONG);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-       break;
-      }
-
-      case ProcessDeviceMap:
-      {
-        PROCESS_DEVICEMAP_INFORMATION DeviceMap;
-          
-        ObQueryDeviceMapInformation(Process, &DeviceMap);
-
-        _SEH_TRY
-        {
-          *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
-         if (ReturnLength)
-          {
-           *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-       break;
-      }
-
-      case ProcessPriorityClass:
-      {
-       PUSHORT Priority = (PUSHORT)ProcessInformation;
-
-       _SEH_TRY
-       {
-         *Priority = Process->PriorityClass;
-
-         if (ReturnLength)
-         {
-           *ReturnLength = sizeof(USHORT);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-       break;
-      }
-
-      case ProcessImageFileName:
-      {
-        /*
-         * We DO NOT return the file name stored in the EPROCESS structure.
-         * Propably if we can't find a PEB or ProcessParameters structure for the
-         * process!
-         */
-        if(Process->Peb != NULL)
-        {
-          PRTL_USER_PROCESS_PARAMETERS ProcParams = NULL;
-          UNICODE_STRING LocalDest;
-          BOOLEAN Attached;
-          ULONG ImagePathLen = 0;
-          PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
-
-          /* we need to attach to the process to make sure we're in the right context! */
-          Attached = Process != PsGetCurrentProcess();
-
-          if(Attached)
-            KeAttachProcess(&Process->Pcb);
-          
-          _SEH_TRY
-          {
-            ProcParams = Process->Peb->ProcessParameters;
-            ImagePathLen = ProcParams->ImagePathName.Length;
-          }
-          _SEH_HANDLE
-          {
-            Status = _SEH_GetExceptionCode();
-          }
-          _SEH_END;
-          
-          if(NT_SUCCESS(Status))
-          {
-            if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
-            {
-              Status = STATUS_INFO_LENGTH_MISMATCH;
-            }
-            else
-            {
-              PWSTR StrSource = NULL;
-
-              /* create a DstPath structure on the stack */
-              _SEH_TRY
-              {
-                LocalDest.Length = ImagePathLen;
-                LocalDest.MaximumLength = ImagePathLen + sizeof(WCHAR);
-                LocalDest.Buffer = (PWSTR)(DstPath + 1);
-
-                /* save a copy of the pointer to the source buffer */
-                StrSource = ProcParams->ImagePathName.Buffer;
-              }
-              _SEH_HANDLE
-              {
-                Status = _SEH_GetExceptionCode();
-              }
-              _SEH_END;
-
-              if(NT_SUCCESS(Status))
-              {
-                /* now, let's allocate some anonymous memory to copy the string to.
-                   we can't just copy it to the buffer the caller pointed as it might
-                   be user memory in another context */
-                PWSTR PathCopy = ExAllocatePool(PagedPool, LocalDest.Length + sizeof(WCHAR));
-                if(PathCopy != NULL)
-                {
-                  /* make a copy of the buffer to the temporary buffer */
-                  _SEH_TRY
-                  {
-                    RtlCopyMemory(PathCopy, StrSource, LocalDest.Length);
-                    PathCopy[LocalDest.Length / sizeof(WCHAR)] = L'\0';
-                  }
-                  _SEH_HANDLE
-                  {
-                    Status = _SEH_GetExceptionCode();
-                  }
-                  _SEH_END;
-
-                  /* detach from the process */
-                  if(Attached)
-                    KeDetachProcess();
-
-                  /* only copy the string back to the caller if we were able to
-                     copy it into the temporary buffer! */
-                  if(NT_SUCCESS(Status))
-                  {
-                    /* now let's copy the buffer back to the caller */
-                    _SEH_TRY
-                    {
-                      *DstPath = LocalDest;
-                      RtlCopyMemory(LocalDest.Buffer, PathCopy, LocalDest.Length + sizeof(WCHAR));
-                      if (ReturnLength)
-                      {
-                        *ReturnLength = sizeof(UNICODE_STRING) + LocalDest.Length + sizeof(WCHAR);
-                      }
-                    }
-                    _SEH_HANDLE
-                    {
-                      Status = _SEH_GetExceptionCode();
-                    }
-                    _SEH_END;
-                  }
-
-                  /* we're done with the copy operation, free the temporary kernel buffer */
-                  ExFreePool(PathCopy);
-
-                  /* we need to bail because we're already detached from the process */
-                  break;
-                }
-                else
-                {
-                  Status = STATUS_INSUFFICIENT_RESOURCES;
-                }
-              }
-            }
-          }
-          
-          /* don't forget to detach from the process!!! */
-          if(Attached)
-            KeDetachProcess();
-        }
-        else
-        {
-          /* FIXME - what to do here? */
-          Status = STATUS_UNSUCCESSFUL;
-        }
-        break;
-      }
-      
-      case ProcessCookie:
-      {
-        ULONG Cookie;
-        
-        /* receive the process cookie, this is only allowed for the current
-           process! */
-
-        Process = PsGetCurrentProcess();
-
-        Cookie = Process->Cookie;
-        if(Cookie == 0)
-        {
-          LARGE_INTEGER SystemTime;
-          ULONG NewCookie;
-          PKPRCB Prcb;
-          
-          /* generate a new cookie */
-          
-          KeQuerySystemTime(&SystemTime);
-          
-          Prcb = KeGetCurrentPrcb();
-
-          NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
-                      SystemTime.u.LowPart ^ SystemTime.u.HighPart;
-          
-          /* try to set the new cookie, return the current one if another thread
-             set it in the meanwhile */
-          Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
-                                              NewCookie,
-                                              Cookie);
-          if(Cookie == 0)
-          {
-            /* successfully set the cookie */
-            Cookie = NewCookie;
-          }
-        }
-        
-        _SEH_TRY
-        {
-          *(PULONG)ProcessInformation = Cookie;
-         if (ReturnLength)
-          {
-           *ReturnLength = sizeof(ULONG);
-         }
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        break;
-      }
-
-      /*
-       * Note: The following 10 information classes are verified to not be
-       * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
-       */
-      case ProcessBasePriority:
-      case ProcessRaisePriority:
-      case ProcessExceptionPort:
-      case ProcessAccessToken:
-      case ProcessLdtSize:
-      case ProcessIoPortHandlers:
-      case ProcessUserModeIOPL:
-      case ProcessEnableAlignmentFaultFixup:
-      case ProcessAffinityMask:
-      case ProcessForegroundInformation:
-      default:
-       Status = STATUS_INVALID_INFO_CLASS;
-     }
-
-   if(ProcessInformationClass != ProcessCookie)
-   {
-     ObDereferenceObject(Process);
-   }
-   
-   return Status;
-}
-
-
-NTSTATUS
-PspAssignPrimaryToken(PEPROCESS Process,
-                     HANDLE TokenHandle)
-{
-   PACCESS_TOKEN Token;
-   PACCESS_TOKEN OldToken;
-   NTSTATUS Status;
-   
-   Status = ObReferenceObjectByHandle(TokenHandle,
-                                     0,
-                                     SepTokenObjectType,
-                                     UserMode,
-                                     (PVOID*)&Token,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-   Status = SeExchangePrimaryToken(Process, Token, &OldToken);
-   if (NT_SUCCESS(Status))
-     {
-       ObDereferenceObject(OldToken);
-     }
-   ObDereferenceObject(Token);
-   return(Status);
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtSetInformationProcess(IN HANDLE ProcessHandle,
-                       IN PROCESSINFOCLASS ProcessInformationClass,
-                       IN PVOID ProcessInformation,
-                       IN ULONG ProcessInformationLength)
-{
-   PEPROCESS Process;
-   KPROCESSOR_MODE PreviousMode;
-   ACCESS_MASK Access;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   PAGED_CODE();
-   
-   PreviousMode = ExGetPreviousMode();
-
-   DefaultSetInfoBufferCheck(ProcessInformationClass,
-                             PsProcessInfoClass,
-                             ProcessInformation,
-                             ProcessInformationLength,
-                             PreviousMode,
-                             &Status);
-   if(!NT_SUCCESS(Status))
-   {
-     DPRINT1("NtSetInformationProcess() %d %x  %x called\n", ProcessInformationClass, ProcessInformation, ProcessInformationLength);
-     DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status);
-     return Status;
-   }
-   
-   switch(ProcessInformationClass)
-   {
-     case ProcessSessionInformation:
-       Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID;
-       break;
-     case ProcessExceptionPort:
-     case ProcessDebugPort:
-       Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT;
-       break;
-
-     default:
-       Access = PROCESS_SET_INFORMATION;
-       break;
-   }
-   
-   Status = ObReferenceObjectByHandle(ProcessHandle,
-                                     Access,
-                                     PsProcessType,
-                                     PreviousMode,
-                                     (PVOID*)&Process,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-
-   switch (ProcessInformationClass)
-     {
-      case ProcessQuotaLimits:
-      case ProcessBasePriority:
-      case ProcessRaisePriority:
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
-
-      case ProcessDebugPort:
-      {
-        HANDLE PortHandle = NULL;
-
-        /* make a safe copy of the buffer on the stack */
-        _SEH_TRY
-        {
-          PortHandle = *(PHANDLE)ProcessInformation;
-          Status = (PortHandle != NULL ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER);
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if(NT_SUCCESS(Status))
-        {
-          PEPORT DebugPort;
-
-          /* in case we had success reading from the buffer, verify the provided
-           * LPC port handle
-           */
-          Status = ObReferenceObjectByHandle(PortHandle,
-                                             0,
-                                             LpcPortObjectType,
-                                             PreviousMode,
-                                             (PVOID)&DebugPort,
-                                             NULL);
-          if(NT_SUCCESS(Status))
-          {
-            /* lock the process to be thread-safe! */
-
-            Status = PsLockProcess(Process, FALSE);
-            if(NT_SUCCESS(Status))
-            {
-              /*
-               * according to "NT Native API" documentation, setting the debug
-               * port is only permitted once!
-               */
-              if(Process->DebugPort == NULL)
-              {
-                /* keep the reference to the handle! */
-                Process->DebugPort = DebugPort;
-                
-                if(Process->Peb)
-                {
-                  /* we're now debugging the process, so set the flag in the PEB
-                     structure. However, to access it we need to attach to the
-                     process so we're sure we're in the right context! */
-
-                  KeAttachProcess(&Process->Pcb);
-                  _SEH_TRY
-                  {
-                    Process->Peb->BeingDebugged = TRUE;
-                  }
-                  _SEH_HANDLE
-                  {
-                    DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process, _SEH_GetExceptionCode());
-                  }
-                  _SEH_END;
-                  KeDetachProcess();
-                }
-                Status = STATUS_SUCCESS;
-              }
-              else
-              {
-                ObDereferenceObject(DebugPort);
-                Status = STATUS_PORT_ALREADY_SET;
-              }
-              PsUnlockProcess(Process);
-            }
-            else
-            {
-              ObDereferenceObject(DebugPort);
-            }
-          }
-        }
-        break;
-      }
-
-      case ProcessExceptionPort:
-      {
-        HANDLE PortHandle = NULL;
-
-        /* make a safe copy of the buffer on the stack */
-        _SEH_TRY
-        {
-          PortHandle = *(PHANDLE)ProcessInformation;
-          Status = STATUS_SUCCESS;
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        if(NT_SUCCESS(Status))
-        {
-          PEPORT ExceptionPort;
-          
-          /* in case we had success reading from the buffer, verify the provided
-           * LPC port handle
-           */
-          Status = ObReferenceObjectByHandle(PortHandle,
-                                             0,
-                                             LpcPortObjectType,
-                                             PreviousMode,
-                                             (PVOID)&ExceptionPort,
-                                             NULL);
-          if(NT_SUCCESS(Status))
-          {
-            /* lock the process to be thread-safe! */
-            
-            Status = PsLockProcess(Process, FALSE);
-            if(NT_SUCCESS(Status))
-            {
-              /*
-               * according to "NT Native API" documentation, setting the exception
-               * port is only permitted once!
-               */
-              if(Process->ExceptionPort == NULL)
-              {
-                /* keep the reference to the handle! */
-                Process->ExceptionPort = ExceptionPort;
-                Status = STATUS_SUCCESS;
-              }
-              else
-              {
-                ObDereferenceObject(ExceptionPort);
-                Status = STATUS_PORT_ALREADY_SET;
-              }
-              PsUnlockProcess(Process);
-            }
-            else
-            {
-              ObDereferenceObject(ExceptionPort);
-            }
-          }
-        }
-        break;
-      }
-
-      case ProcessAccessToken:
-      {
-        HANDLE TokenHandle = NULL;
-
-        /* make a safe copy of the buffer on the stack */
-        _SEH_TRY
-        {
-          TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->Token;
-          Status = STATUS_SUCCESS;
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if(NT_SUCCESS(Status))
-        {
-          /* in case we had success reading from the buffer, perform the actual task */
-          Status = PspAssignPrimaryToken(Process, TokenHandle);
-        }
-       break;
-      }
-
-      case ProcessDefaultHardErrorMode:
-      {
-        _SEH_TRY
-        {
-          InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
-                              *(PLONG)ProcessInformation);
-          Status = STATUS_SUCCESS;
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        break;
-      }
-      
-      case ProcessSessionInformation:
-      {
-        PROCESS_SESSION_INFORMATION SessionInfo;
-        Status = STATUS_SUCCESS;
-        
-        _SEH_TRY
-        {
-          /* copy the structure to the stack */
-          SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        if(NT_SUCCESS(Status))
-        {
-          /* we successfully copied the structure to the stack, continue processing */
-          
-          /*
-           * setting the session id requires the SeTcbPrivilege!
-           */
-          if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
-                                     PreviousMode))
-          {
-            DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
-            /* can't set the session id, bail! */
-            Status = STATUS_PRIVILEGE_NOT_HELD;
-            break;
-          }
-          
-          /* FIXME - update the session id for the process token */
-
-          Status = PsLockProcess(Process, FALSE);
-          if(NT_SUCCESS(Status))
-          {
-            Process->SessionId = SessionInfo.SessionId;
-
-            /* Update the session id in the PEB structure */
-            if(Process->Peb != NULL)
-            {
-              /* we need to attach to the process to make sure we're in the right
-                 context to access the PEB structure */
-              KeAttachProcess(&Process->Pcb);
-
-              _SEH_TRY
-              {
-                /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
-
-                Status = STATUS_SUCCESS;
-              }
-              _SEH_HANDLE
-              {
-                Status = _SEH_GetExceptionCode();
-              }
-              _SEH_END;
-
-              KeDetachProcess();
-            }
-
-            PsUnlockProcess(Process);
-          }
-        }
-        break;
-      }
-      
-      case ProcessPriorityClass:
-      {
-        PROCESS_PRIORITY_CLASS ppc;
-
-        _SEH_TRY
-        {
-          ppc = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
-        }
-        _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        if(NT_SUCCESS(Status))
-        {
-        }
-        
-        break;
-      }
-       
-      case ProcessLdtInformation:
-      case ProcessLdtSize:
-      case ProcessIoPortHandlers:
-      case ProcessWorkingSetWatch:
-      case ProcessUserModeIOPL:
-      case ProcessEnableAlignmentFaultFixup:
-      case ProcessAffinityMask:
-       Status = STATUS_NOT_IMPLEMENTED;
-       break;
-
-      case ProcessBasicInformation:
-      case ProcessIoCounters:
-      case ProcessTimes:
-      case ProcessPooledUsageAndLimits:
-      case ProcessWx86Information:
-      case ProcessHandleCount:
-      case ProcessWow64Information:
-      default:
-       Status = STATUS_INVALID_INFO_CLASS;
-     }
-   ObDereferenceObject(Process);
-   return(Status);
-}
-
-
-/**********************************************************************
- * NAME                                                        INTERNAL
- *     PiQuerySystemProcessInformation
- *
- * DESCRIPTION
- *     Compute the size of a process+thread snapshot as 
- *     expected by NtQuerySystemInformation.
- *
- * RETURN VALUE
- *     0 on error; otherwise the size, in bytes of the buffer
- *     required to write a full snapshot.
- *
- * NOTE
- *     We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
- */
-NTSTATUS
-PiQuerySystemProcessInformation(PVOID Buffer,
-                               ULONG Size,
-                               PULONG ReqSize)
-{
-   return STATUS_NOT_IMPLEMENTED;
-
-#if 0
-       PLIST_ENTRY     CurrentEntryP;
-       PEPROCESS       CurrentP;
-       PLIST_ENTRY     CurrentEntryT;
-       PETHREAD        CurrentT;
-       
-       ULONG           RequiredSize = 0L;
-       BOOLEAN         SizeOnly = FALSE;
-
-       ULONG           SpiSize = 0L;
-       
-       PSYSTEM_PROCESS_INFORMATION     pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
-       PSYSTEM_PROCESS_INFORMATION     pInfoPLast = NULL;
-       PSYSTEM_THREAD_INFO             pInfoT = NULL;
-       
-
-   /* Lock the process list. */
-   ExAcquireFastMutex(&PspActiveProcessMutex);
-
-       /*
-        * Scan the process list. Since the
-        * list is circular, the guard is false
-        * after the last process.
-        */
-       for (   CurrentEntryP = PsActiveProcessHead.Flink;
-               (CurrentEntryP != & PsActiveProcessHead);
-               CurrentEntryP = CurrentEntryP->Flink
-               )
-       {
-               /*
-                * Compute how much space is
-                * occupied in the snapshot
-                * by adding this process info.
-                * (at least one thread).
-                */
-               SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
-               RequiredSize += SpiSizeCurrent;
-               /*
-                * Do not write process data in the
-                * buffer if it is too small.
-                */
-               if (TRUE == SizeOnly) continue;
-               /*
-                * Check if the buffer can contain
-                * the full snapshot.
-                */
-               if (Size < RequiredSize)
-               {
-                       SizeOnly = TRUE;
-                       continue;
-               }
-               /* 
-                * Get a reference to the 
-                * process descriptor we are
-                * handling.
-                */
-               CurrentP = CONTAINING_RECORD(
-                               CurrentEntryP,
-                               EPROCESS, 
-                               ProcessListEntry
-                               );
-               /*
-                * Write process data in the buffer.
-                */
-               RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
-               /* PROCESS */
-               pInfoP->ThreadCount = 0L;
-               pInfoP->ProcessId = CurrentP->UniqueProcessId;
-               RtlInitUnicodeString (
-                       & pInfoP->Name,
-                       CurrentP->ImageFileName
-                       );
-               /* THREAD */
-               for (   pInfoT = & CurrentP->ThreadSysInfo [0],
-                       CurrentEntryT = CurrentP->ThreadListHead.Flink;
-                       
-                       (CurrentEntryT != & CurrentP->ThreadListHead);
-                       
-                       pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
-                       CurrentEntryT = CurrentEntryT->Flink
-                       )
-               {
-                       /*
-                        * Recalculate the size of the
-                        * information block.
-                        */
-                       if (0 < pInfoP->ThreadCount)
-                       {
-                               RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
-                       }
-                       /*
-                        * Do not write thread data in the
-                        * buffer if it is too small.
-                        */
-                       if (TRUE == SizeOnly) continue;
-                       /*
-                        * Check if the buffer can contain
-                        * the full snapshot.
-                        */
-                       if (Size < RequiredSize)
-                       {
-                               SizeOnly = TRUE;
-                               continue;
-                       }
-                       /* 
-                        * Get a reference to the 
-                        * thread descriptor we are
-                        * handling.
-                        */
-                       CurrentT = CONTAINING_RECORD(
-                                       CurrentEntryT,
-                                       KTHREAD, 
-                                       ThreadListEntry
-                                       );
-                       /*
-                        * Write thread data.
-                        */
-                       RtlZeroMemory (
-                               pInfoT,
-                               sizeof (SYSTEM_THREAD_INFORMATION)
-                               );
-                       pInfoT->KernelTime      = CurrentT-> ;  /* TIME */
-                       pInfoT->UserTime        = CurrentT-> ;  /* TIME */
-                       pInfoT->CreateTime      = CurrentT-> ;  /* TIME */
-                       pInfoT->TickCount       = CurrentT-> ;  /* ULONG */
-                       pInfoT->StartEIP        = CurrentT-> ;  /* ULONG */
-                       pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
-                       pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
-                       pInfoT->DynamicPriority = CurrentT-> ;  /* ULONG */
-                       pInfoT->BasePriority    = CurrentT-> ;  /* ULONG */
-                       pInfoT->nSwitches       = CurrentT-> ;  /* ULONG */
-                       pInfoT->State           = CurrentT-> ;  /* DWORD */
-                       pInfoT->WaitReason      = CurrentT-> ;  /* KWAIT_REASON */
-                       /*
-                        * Count the number of threads 
-                        * this process has.
-                        */
-                       ++ pInfoP->ThreadCount;
-               }
-               /*
-                * Save the size of information
-                * stored in the buffer for the
-                * current process.
-                */
-               pInfoP->RelativeOffset = SpiSize;
-               /*
-                * Save a reference to the last
-                * valid information block.
-                */
-               pInfoPLast = pInfoP;
-               /*
-                * Compute the offset of the 
-                * SYSTEM_PROCESS_INFORMATION
-                * descriptor in the snapshot 
-                * buffer for the next process.
-                */
-               (ULONG) pInfoP += SpiSize;
-       }
-       /*
-        * Unlock the process list.
-        */
-       ExReleaseFastMutex (
-               & PspActiveProcessMutex
-               );
-       /*
-        * Return the proper error status code,
-        * if the buffer was too small.
-        */
-       if (TRUE == SizeOnly)
-       {
-               if (NULL != RequiredSize)
-               {
-                       *pRequiredSize = RequiredSize;
-               }
-               return STATUS_INFO_LENGTH_MISMATCH;
-       }
-       /*
-        * Mark the end of the snapshot.
-        */
-       pInfoP->RelativeOffset = 0L;
-       /* OK */        
-       return STATUS_SUCCESS;
-#endif
-}
-
 /*
  * @implemented
  */
@@ -3039,12 +1659,6 @@ PsLockProcess(PEPROCESS Process, BOOL Timeout)
   
   for(;;)
   {
-    if(Process->Pcb.State == PROCESS_STATE_TERMINATED)
-    {
-      KeLeaveCriticalRegion();
-      return STATUS_PROCESS_IS_TERMINATING;
-    }
-
     PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
       &Process->LockOwner, CallingThread, NULL);
     if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
index 52d9fa6..d8070ab 100644 (file)
@@ -30,8 +30,6 @@ PiInitProcessManager(VOID)
    PsInitProcessManagment();
    PsInitThreadManagment();
    PsInitIdleThread();
-   PsInitReaperThread();
-   PsInitialiseSuspendImplementation();
    PsInitialiseW32Call();
 }
 
diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c
new file mode 100644 (file)
index 0000000..b6dbac1
--- /dev/null
@@ -0,0 +1,1414 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/query.c
+ * PURPOSE:         Set/Query Process/Thread Information APIs
+ *
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net) - Created File
+ *                  David Welch
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* GLOBALS ******************************************************************/
+
+
+static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
+{
+  ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION),     sizeof(ULONG), ICIF_QUERY ),                     /* ProcessBasicInformation */
+  ICI_SQ_SAME( sizeof(QUOTA_LIMITS),                  sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessQuotaLimits */
+  ICI_SQ_SAME( sizeof(IO_COUNTERS),                   sizeof(ULONG), ICIF_QUERY ),                     /* ProcessIoCounters */
+  ICI_SQ_SAME( sizeof(VM_COUNTERS),                   sizeof(ULONG), ICIF_QUERY ),                     /* ProcessVmCounters */
+  ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES),             sizeof(ULONG), ICIF_QUERY ),                     /* ProcessTimes */
+  ICI_SQ_SAME( sizeof(KPRIORITY),                     sizeof(ULONG), ICIF_SET ),                       /* ProcessBasePriority */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_SET ),                       /* ProcessRaisePriority */
+  ICI_SQ_SAME( sizeof(HANDLE),                        sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessDebugPort */
+  ICI_SQ_SAME( sizeof(HANDLE),                        sizeof(ULONG), ICIF_SET ),                       /* ProcessExceptionPort */
+  ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN),          sizeof(ULONG), ICIF_SET ),                       /* ProcessAccessToken */
+  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessLdtInformation */
+  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessLdtSize */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessDefaultHardErrorMode */
+  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessIoPortHandlers */
+  ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS),       sizeof(ULONG), ICIF_QUERY ),                     /* ProcessPooledUsageAndLimits */
+  ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION),  sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessWorkingSetWatch */
+  ICI_SQ_SAME( 0 /* FIXME */,                         sizeof(ULONG), ICIF_SET ),                       /* ProcessUserModeIOPL */
+  ICI_SQ_SAME( sizeof(BOOLEAN),                       sizeof(ULONG), ICIF_SET ),                       /* ProcessEnableAlignmentFaultFixup */
+  ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS),        sizeof(USHORT), ICIF_QUERY | ICIF_SET ),         /* ProcessPriorityClass */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessWx86Information */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessHandleCount */
+  ICI_SQ_SAME( sizeof(KAFFINITY),                     sizeof(ULONG), ICIF_SET ),                       /* ProcessAffinityMask */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessPriorityBoost */
+
+  ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query),                                   /* ProcessDeviceMap */
+         /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set),
+                                                /*Q*/ sizeof(ULONG),
+                                                /*S*/ sizeof(ULONG),
+                                                                     ICIF_QUERY | ICIF_SET ),
+
+  ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION),   sizeof(ULONG), ICIF_QUERY | ICIF_SET ),          /* ProcessSessionInformation */
+  ICI_SQ_SAME( sizeof(BOOLEAN),                       sizeof(ULONG), ICIF_SET ),                       /* ProcessForegroundInformation */
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY ),                     /* ProcessWow64Information */
+  ICI_SQ_SAME( sizeof(UNICODE_STRING),                sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */
+
+  /* FIXME */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessLUIDDeviceMapsEnabled */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessBreakOnTermination */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessDebugObjectHandle */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessDebugFlags */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessHandleTracing */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown33 */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown34 */
+  ICI_SQ_SAME( 0,                                     1,             0 ),                              /* ProcessUnknown35 */
+  
+  ICI_SQ_SAME( sizeof(ULONG),                         sizeof(ULONG), ICIF_QUERY),                      /* ProcessCookie */
+};
+
+/*
+ * FIXME:
+ *   Remove the Implemented value if all functions are implemented.
+ */
+
+static const struct
+{
+   BOOLEAN Implemented;
+   ULONG Size;
+} QueryInformationData[MaxThreadInfoClass + 1] = 
+{
+    {TRUE, sizeof(THREAD_BASIC_INFORMATION)},  // ThreadBasicInformation
+    {TRUE, sizeof(KERNEL_USER_TIMES)},         // ThreadTimes
+    {TRUE, 0},                                 // ThreadPriority
+    {TRUE, 0},                                 // ThreadBasePriority
+    {TRUE, 0},                                 // ThreadAffinityMask
+    {TRUE, 0},                                 // ThreadImpersonationToken
+    {FALSE, 0},                                        // ThreadDescriptorTableEntry
+    {TRUE, 0},                                 // ThreadEnableAlignmentFaultFixup
+    {TRUE, 0},                                 // ThreadEventPair
+    {TRUE, sizeof(PVOID)},                     // ThreadQuerySetWin32StartAddress
+    {TRUE, 0},                                 // ThreadZeroTlsCell
+    {TRUE, sizeof(LARGE_INTEGER)},             // ThreadPerformanceCount
+    {TRUE, sizeof(BOOLEAN)},                   // ThreadAmILastThread
+    {TRUE, 0},                                 // ThreadIdealProcessor
+    {FALSE, 0},                                        // ThreadPriorityBoost
+    {TRUE, 0},                                 // ThreadSetTlsArrayAddress
+    {FALSE, 0},                                        // ThreadIsIoPending
+    {TRUE, 0}                                  // ThreadHideFromDebugger
+};
+
+static const struct
+{
+   BOOLEAN Implemented;
+   ULONG Size;
+} SetInformationData[MaxThreadInfoClass + 1] = 
+{
+    {TRUE, 0},                 // ThreadBasicInformation
+    {TRUE, 0},                 // ThreadTimes
+    {TRUE, sizeof(KPRIORITY)}, // ThreadPriority
+    {TRUE, sizeof(LONG)},      // ThreadBasePriority
+    {TRUE, sizeof(KAFFINITY)}, // ThreadAffinityMask
+    {TRUE, sizeof(HANDLE)},    // ThreadImpersonationToken
+    {TRUE, 0},                 // ThreadDescriptorTableEntry
+    {FALSE, 0},                        // ThreadEnableAlignmentFaultFixup
+    {FALSE, 0},                        // ThreadEventPair
+    {TRUE, sizeof(PVOID)},     // ThreadQuerySetWin32StartAddress
+    {FALSE, 0},                        // ThreadZeroTlsCell
+    {TRUE, 0},                 // ThreadPerformanceCount
+    {TRUE, 0},                 // ThreadAmILastThread
+    {FALSE, 0},                        // ThreadIdealProcessor
+    {FALSE, 0},                        // ThreadPriorityBoost
+    {FALSE, 0},                        // ThreadSetTlsArrayAddress
+    {TRUE, 0},                 // ThreadIsIoPending
+    {FALSE, 0}                 // ThreadHideFromDebugger
+};
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+NtQueryInformationProcess(IN  HANDLE ProcessHandle,
+                         IN  PROCESSINFOCLASS ProcessInformationClass,
+                         OUT PVOID ProcessInformation,
+                         IN  ULONG ProcessInformationLength,
+                         OUT PULONG ReturnLength  OPTIONAL)
+{
+   PEPROCESS Process;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   PAGED_CODE();
+   
+   PreviousMode = ExGetPreviousMode();
+   
+   DefaultQueryInfoBufferCheck(ProcessInformationClass,
+                               PsProcessInfoClass,
+                               ProcessInformation,
+                               ProcessInformationLength,
+                               ReturnLength,
+                               PreviousMode,
+                               &Status);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
+     return Status;
+   }
+   
+   if(ProcessInformationClass != ProcessCookie)
+   {
+     Status = ObReferenceObjectByHandle(ProcessHandle,
+                                     PROCESS_QUERY_INFORMATION,
+                                     PsProcessType,
+                                     PreviousMode,
+                                     (PVOID*)&Process,
+                                     NULL);
+     if (!NT_SUCCESS(Status))
+       {
+       return(Status);
+       }
+   }
+   else if(ProcessHandle != NtCurrentProcess())
+   {
+     /* retreiving the process cookie is only allowed for the calling process
+        itself! XP only allowes NtCurrentProcess() as process handles even if a
+        real handle actually represents the current process. */
+     return STATUS_INVALID_PARAMETER;
+   }
+   
+   switch (ProcessInformationClass)
+     {
+      case ProcessBasicInformation:
+      {
+        PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
+         (PPROCESS_BASIC_INFORMATION)ProcessInformation;
+
+        _SEH_TRY
+        {
+         ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
+         ProcessBasicInformationP->PebBaseAddress = Process->Peb;
+         ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
+         ProcessBasicInformationP->UniqueProcessId =
+           Process->UniqueProcessId;
+         ProcessBasicInformationP->InheritedFromUniqueProcessId =
+           Process->InheritedFromUniqueProcessId;
+         ProcessBasicInformationP->BasePriority =
+           Process->Pcb.BasePriority;
+
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+       break;
+      }
+
+      case ProcessQuotaLimits:
+      case ProcessIoCounters:
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
+
+      case ProcessTimes:
+      {
+         PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation;
+         _SEH_TRY
+         {
+           ProcessTimeP->CreateTime = Process->CreateTime;
+            ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL;
+            ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL;
+           ProcessTimeP->ExitTime = Process->ExitTime;
+
+          if (ReturnLength)
+          {
+            *ReturnLength = sizeof(KERNEL_USER_TIMES);
+          }
+         }
+         _SEH_HANDLE
+         {
+           Status = _SEH_GetExceptionCode();
+         }
+         _SEH_END;
+        break;
+      }
+
+      case ProcessDebugPort:
+      {
+        _SEH_TRY
+        {
+          *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL);
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(HANDLE);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        break;
+      }
+      
+      case ProcessLdtInformation:
+      case ProcessWorkingSetWatch:
+      case ProcessWx86Information:
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
+
+      case ProcessHandleCount:
+      {
+       ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
+         
+       _SEH_TRY
+       {
+          *(PULONG)ProcessInformation = HandleCount;
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(ULONG);
+         }
+       }
+       _SEH_HANDLE
+       {
+          Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+       break;
+      }
+
+      case ProcessSessionInformation:
+      {
+        PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation;
+
+        _SEH_TRY
+        {
+          SessionInfo->SessionId = Process->SessionId;
+          if (ReturnLength)
+          {
+            *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
+          }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        break;
+      }
+      
+      case ProcessWow64Information:
+        DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
+
+      case ProcessVmCounters:
+      {
+       PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
+         
+       _SEH_TRY
+       {
+         pOut->PeakVirtualSize            = Process->PeakVirtualSize;
+         /*
+          * Here we should probably use VirtualSize.LowPart, but due to
+          * incompatibilities in current headers (no unnamed union),
+          * I opted for cast.
+          */
+         pOut->VirtualSize                = (ULONG)Process->VirtualSize.QuadPart;
+         pOut->PageFaultCount             = Process->Vm.PageFaultCount;
+         pOut->PeakWorkingSetSize         = Process->Vm.PeakWorkingSetSize;
+         pOut->WorkingSetSize             = Process->Vm.WorkingSetSize;
+         pOut->QuotaPeakPagedPoolUsage    = Process->QuotaPeakPoolUsage[0]; // TODO: Verify!
+         pOut->QuotaPagedPoolUsage        = Process->QuotaPoolUsage[0];     // TODO: Verify!
+         pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeakPoolUsage[1]; // TODO: Verify!
+         pOut->QuotaNonPagedPoolUsage     = Process->QuotaPoolUsage[1];     // TODO: Verify!
+         pOut->PagefileUsage              = Process->PagefileUsage;
+         pOut->PeakPagefileUsage          = Process->PeakPagefileUsage;
+
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(VM_COUNTERS);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+       break;
+      }
+
+      case ProcessDefaultHardErrorMode:
+      {
+       PULONG HardErrMode = (PULONG)ProcessInformation;
+       _SEH_TRY
+       {
+         *HardErrMode = Process->DefaultHardErrorProcessing;
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(ULONG);
+         }
+       }
+       _SEH_HANDLE
+       {
+          Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+       break;
+      }
+
+      case ProcessPriorityBoost:
+      {
+       PULONG BoostEnabled = (PULONG)ProcessInformation;
+         
+       _SEH_TRY
+       {
+         *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
+
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(ULONG);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+       break;
+      }
+
+      case ProcessDeviceMap:
+      {
+        PROCESS_DEVICEMAP_INFORMATION DeviceMap;
+          
+        ObQueryDeviceMapInformation(Process, &DeviceMap);
+
+        _SEH_TRY
+        {
+          *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
+         if (ReturnLength)
+          {
+           *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+       break;
+      }
+
+      case ProcessPriorityClass:
+      {
+       PUSHORT Priority = (PUSHORT)ProcessInformation;
+
+       _SEH_TRY
+       {
+         *Priority = Process->PriorityClass;
+
+         if (ReturnLength)
+         {
+           *ReturnLength = sizeof(USHORT);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+       break;
+      }
+
+      case ProcessImageFileName:
+      {
+        /*
+         * We DO NOT return the file name stored in the EPROCESS structure.
+         * Propably if we can't find a PEB or ProcessParameters structure for the
+         * process!
+         */
+        if(Process->Peb != NULL)
+        {
+          PRTL_USER_PROCESS_PARAMETERS ProcParams = NULL;
+          UNICODE_STRING LocalDest;
+          BOOLEAN Attached;
+          ULONG ImagePathLen = 0;
+          PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
+
+          /* we need to attach to the process to make sure we're in the right context! */
+          Attached = Process != PsGetCurrentProcess();
+
+          if(Attached)
+            KeAttachProcess(&Process->Pcb);
+          
+          _SEH_TRY
+          {
+            ProcParams = Process->Peb->ProcessParameters;
+            ImagePathLen = ProcParams->ImagePathName.Length;
+          }
+          _SEH_HANDLE
+          {
+            Status = _SEH_GetExceptionCode();
+          }
+          _SEH_END;
+          
+          if(NT_SUCCESS(Status))
+          {
+            if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
+            {
+              Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            else
+            {
+              PWSTR StrSource = NULL;
+
+              /* create a DstPath structure on the stack */
+              _SEH_TRY
+              {
+                LocalDest.Length = ImagePathLen;
+                LocalDest.MaximumLength = ImagePathLen + sizeof(WCHAR);
+                LocalDest.Buffer = (PWSTR)(DstPath + 1);
+
+                /* save a copy of the pointer to the source buffer */
+                StrSource = ProcParams->ImagePathName.Buffer;
+              }
+              _SEH_HANDLE
+              {
+                Status = _SEH_GetExceptionCode();
+              }
+              _SEH_END;
+
+              if(NT_SUCCESS(Status))
+              {
+                /* now, let's allocate some anonymous memory to copy the string to.
+                   we can't just copy it to the buffer the caller pointed as it might
+                   be user memory in another context */
+                PWSTR PathCopy = ExAllocatePool(PagedPool, LocalDest.Length + sizeof(WCHAR));
+                if(PathCopy != NULL)
+                {
+                  /* make a copy of the buffer to the temporary buffer */
+                  _SEH_TRY
+                  {
+                    RtlCopyMemory(PathCopy, StrSource, LocalDest.Length);
+                    PathCopy[LocalDest.Length / sizeof(WCHAR)] = L'\0';
+                  }
+                  _SEH_HANDLE
+                  {
+                    Status = _SEH_GetExceptionCode();
+                  }
+                  _SEH_END;
+
+                  /* detach from the process */
+                  if(Attached)
+                    KeDetachProcess();
+
+                  /* only copy the string back to the caller if we were able to
+                     copy it into the temporary buffer! */
+                  if(NT_SUCCESS(Status))
+                  {
+                    /* now let's copy the buffer back to the caller */
+                    _SEH_TRY
+                    {
+                      *DstPath = LocalDest;
+                      RtlCopyMemory(LocalDest.Buffer, PathCopy, LocalDest.Length + sizeof(WCHAR));
+                      if (ReturnLength)
+                      {
+                        *ReturnLength = sizeof(UNICODE_STRING) + LocalDest.Length + sizeof(WCHAR);
+                      }
+                    }
+                    _SEH_HANDLE
+                    {
+                      Status = _SEH_GetExceptionCode();
+                    }
+                    _SEH_END;
+                  }
+
+                  /* we're done with the copy operation, free the temporary kernel buffer */
+                  ExFreePool(PathCopy);
+
+                  /* we need to bail because we're already detached from the process */
+                  break;
+                }
+                else
+                {
+                  Status = STATUS_INSUFFICIENT_RESOURCES;
+                }
+              }
+            }
+          }
+          
+          /* don't forget to detach from the process!!! */
+          if(Attached)
+            KeDetachProcess();
+        }
+        else
+        {
+          /* FIXME - what to do here? */
+          Status = STATUS_UNSUCCESSFUL;
+        }
+        break;
+      }
+      
+      case ProcessCookie:
+      {
+        ULONG Cookie;
+        
+        /* receive the process cookie, this is only allowed for the current
+           process! */
+
+        Process = PsGetCurrentProcess();
+
+        Cookie = Process->Cookie;
+        if(Cookie == 0)
+        {
+          LARGE_INTEGER SystemTime;
+          ULONG NewCookie;
+          PKPRCB Prcb;
+          
+          /* generate a new cookie */
+          
+          KeQuerySystemTime(&SystemTime);
+          
+          Prcb = KeGetCurrentPrcb();
+
+          NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
+                      SystemTime.u.LowPart ^ SystemTime.u.HighPart;
+          
+          /* try to set the new cookie, return the current one if another thread
+             set it in the meanwhile */
+          Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
+                                              NewCookie,
+                                              Cookie);
+          if(Cookie == 0)
+          {
+            /* successfully set the cookie */
+            Cookie = NewCookie;
+          }
+        }
+        
+        _SEH_TRY
+        {
+          *(PULONG)ProcessInformation = Cookie;
+         if (ReturnLength)
+          {
+           *ReturnLength = sizeof(ULONG);
+         }
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        break;
+      }
+
+      /*
+       * Note: The following 10 information classes are verified to not be
+       * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
+       */
+      case ProcessBasePriority:
+      case ProcessRaisePriority:
+      case ProcessExceptionPort:
+      case ProcessAccessToken:
+      case ProcessLdtSize:
+      case ProcessIoPortHandlers:
+      case ProcessUserModeIOPL:
+      case ProcessEnableAlignmentFaultFixup:
+      case ProcessAffinityMask:
+      case ProcessForegroundInformation:
+      default:
+       Status = STATUS_INVALID_INFO_CLASS;
+     }
+
+   if(ProcessInformationClass != ProcessCookie)
+   {
+     ObDereferenceObject(Process);
+   }
+   
+   return Status;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+NtSetInformationProcess(IN HANDLE ProcessHandle,
+                       IN PROCESSINFOCLASS ProcessInformationClass,
+                       IN PVOID ProcessInformation,
+                       IN ULONG ProcessInformationLength)
+{
+   PEPROCESS Process;
+   KPROCESSOR_MODE PreviousMode;
+   ACCESS_MASK Access;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   PAGED_CODE();
+   
+   PreviousMode = ExGetPreviousMode();
+
+   DefaultSetInfoBufferCheck(ProcessInformationClass,
+                             PsProcessInfoClass,
+                             ProcessInformation,
+                             ProcessInformationLength,
+                             PreviousMode,
+                             &Status);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtSetInformationProcess() %d %x  %x called\n", ProcessInformationClass, ProcessInformation, ProcessInformationLength);
+     DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status);
+     return Status;
+   }
+   
+   switch(ProcessInformationClass)
+   {
+     case ProcessSessionInformation:
+       Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID;
+       break;
+     case ProcessExceptionPort:
+     case ProcessDebugPort:
+       Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT;
+       break;
+
+     default:
+       Access = PROCESS_SET_INFORMATION;
+       break;
+   }
+   
+   Status = ObReferenceObjectByHandle(ProcessHandle,
+                                     Access,
+                                     PsProcessType,
+                                     PreviousMode,
+                                     (PVOID*)&Process,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+
+   switch (ProcessInformationClass)
+     {
+      case ProcessQuotaLimits:
+      case ProcessBasePriority:
+      case ProcessRaisePriority:
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
+
+      case ProcessDebugPort:
+      {
+        HANDLE PortHandle = NULL;
+
+        /* make a safe copy of the buffer on the stack */
+        _SEH_TRY
+        {
+          PortHandle = *(PHANDLE)ProcessInformation;
+          Status = (PortHandle != NULL ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER);
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if(NT_SUCCESS(Status))
+        {
+          PEPORT DebugPort;
+
+          /* in case we had success reading from the buffer, verify the provided
+           * LPC port handle
+           */
+          Status = ObReferenceObjectByHandle(PortHandle,
+                                             0,
+                                             LpcPortObjectType,
+                                             PreviousMode,
+                                             (PVOID)&DebugPort,
+                                             NULL);
+          if(NT_SUCCESS(Status))
+          {
+            /* lock the process to be thread-safe! */
+
+            Status = PsLockProcess(Process, FALSE);
+            if(NT_SUCCESS(Status))
+            {
+              /*
+               * according to "NT Native API" documentation, setting the debug
+               * port is only permitted once!
+               */
+              if(Process->DebugPort == NULL)
+              {
+                /* keep the reference to the handle! */
+                Process->DebugPort = DebugPort;
+                
+                if(Process->Peb)
+                {
+                  /* we're now debugging the process, so set the flag in the PEB
+                     structure. However, to access it we need to attach to the
+                     process so we're sure we're in the right context! */
+
+                  KeAttachProcess(&Process->Pcb);
+                  _SEH_TRY
+                  {
+                    Process->Peb->BeingDebugged = TRUE;
+                  }
+                  _SEH_HANDLE
+                  {
+                    DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process, _SEH_GetExceptionCode());
+                  }
+                  _SEH_END;
+                  KeDetachProcess();
+                }
+                Status = STATUS_SUCCESS;
+              }
+              else
+              {
+                ObDereferenceObject(DebugPort);
+                Status = STATUS_PORT_ALREADY_SET;
+              }
+              PsUnlockProcess(Process);
+            }
+            else
+            {
+              ObDereferenceObject(DebugPort);
+            }
+          }
+        }
+        break;
+      }
+
+      case ProcessExceptionPort:
+      {
+        HANDLE PortHandle = NULL;
+
+        /* make a safe copy of the buffer on the stack */
+        _SEH_TRY
+        {
+          PortHandle = *(PHANDLE)ProcessInformation;
+          Status = STATUS_SUCCESS;
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        if(NT_SUCCESS(Status))
+        {
+          PEPORT ExceptionPort;
+          
+          /* in case we had success reading from the buffer, verify the provided
+           * LPC port handle
+           */
+          Status = ObReferenceObjectByHandle(PortHandle,
+                                             0,
+                                             LpcPortObjectType,
+                                             PreviousMode,
+                                             (PVOID)&ExceptionPort,
+                                             NULL);
+          if(NT_SUCCESS(Status))
+          {
+            /* lock the process to be thread-safe! */
+            
+            Status = PsLockProcess(Process, FALSE);
+            if(NT_SUCCESS(Status))
+            {
+              /*
+               * according to "NT Native API" documentation, setting the exception
+               * port is only permitted once!
+               */
+              if(Process->ExceptionPort == NULL)
+              {
+                /* keep the reference to the handle! */
+                Process->ExceptionPort = ExceptionPort;
+                Status = STATUS_SUCCESS;
+              }
+              else
+              {
+                ObDereferenceObject(ExceptionPort);
+                Status = STATUS_PORT_ALREADY_SET;
+              }
+              PsUnlockProcess(Process);
+            }
+            else
+            {
+              ObDereferenceObject(ExceptionPort);
+            }
+          }
+        }
+        break;
+      }
+
+      case ProcessAccessToken:
+      {
+        HANDLE TokenHandle = NULL;
+
+        /* make a safe copy of the buffer on the stack */
+        _SEH_TRY
+        {
+          TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->Token;
+          Status = STATUS_SUCCESS;
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if(NT_SUCCESS(Status))
+        {
+          /* in case we had success reading from the buffer, perform the actual task */
+          Status = PspAssignPrimaryToken(Process, TokenHandle);
+        }
+       break;
+      }
+
+      case ProcessDefaultHardErrorMode:
+      {
+        _SEH_TRY
+        {
+          InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
+                              *(PLONG)ProcessInformation);
+          Status = STATUS_SUCCESS;
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        break;
+      }
+      
+      case ProcessSessionInformation:
+      {
+        PROCESS_SESSION_INFORMATION SessionInfo;
+        Status = STATUS_SUCCESS;
+        
+        _SEH_TRY
+        {
+          /* copy the structure to the stack */
+          SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        if(NT_SUCCESS(Status))
+        {
+          /* we successfully copied the structure to the stack, continue processing */
+          
+          /*
+           * setting the session id requires the SeTcbPrivilege!
+           */
+          if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
+                                     PreviousMode))
+          {
+            DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
+            /* can't set the session id, bail! */
+            Status = STATUS_PRIVILEGE_NOT_HELD;
+            break;
+          }
+          
+          /* FIXME - update the session id for the process token */
+
+          Status = PsLockProcess(Process, FALSE);
+          if(NT_SUCCESS(Status))
+          {
+            Process->SessionId = SessionInfo.SessionId;
+
+            /* Update the session id in the PEB structure */
+            if(Process->Peb != NULL)
+            {
+              /* we need to attach to the process to make sure we're in the right
+                 context to access the PEB structure */
+              KeAttachProcess(&Process->Pcb);
+
+              _SEH_TRY
+              {
+                /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
+
+                Status = STATUS_SUCCESS;
+              }
+              _SEH_HANDLE
+              {
+                Status = _SEH_GetExceptionCode();
+              }
+              _SEH_END;
+
+              KeDetachProcess();
+            }
+
+            PsUnlockProcess(Process);
+          }
+        }
+        break;
+      }
+      
+      case ProcessPriorityClass:
+      {
+        PROCESS_PRIORITY_CLASS ppc;
+
+        _SEH_TRY
+        {
+          ppc = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
+        }
+        _SEH_HANDLE
+        {
+          Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+        
+        if(NT_SUCCESS(Status))
+        {
+        }
+        
+        break;
+      }
+       
+      case ProcessLdtInformation:
+      case ProcessLdtSize:
+      case ProcessIoPortHandlers:
+      case ProcessWorkingSetWatch:
+      case ProcessUserModeIOPL:
+      case ProcessEnableAlignmentFaultFixup:
+      case ProcessAffinityMask:
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
+
+      case ProcessBasicInformation:
+      case ProcessIoCounters:
+      case ProcessTimes:
+      case ProcessPooledUsageAndLimits:
+      case ProcessWx86Information:
+      case ProcessHandleCount:
+      case ProcessWow64Information:
+      default:
+       Status = STATUS_INVALID_INFO_CLASS;
+     }
+   ObDereferenceObject(Process);
+   return(Status);
+}
+
+
+/**********************************************************************
+ * NAME                                                        INTERNAL
+ *     PiQuerySystemProcessInformation
+ *
+ * DESCRIPTION
+ *     Compute the size of a process+thread snapshot as 
+ *     expected by NtQuerySystemInformation.
+ *
+ * RETURN VALUE
+ *     0 on error; otherwise the size, in bytes of the buffer
+ *     required to write a full snapshot.
+ *
+ * NOTE
+ *     We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
+ */
+NTSTATUS
+PiQuerySystemProcessInformation(PVOID Buffer,
+                               ULONG Size,
+                               PULONG ReqSize)
+{
+   return STATUS_NOT_IMPLEMENTED;
+
+#if 0
+       PLIST_ENTRY     CurrentEntryP;
+       PEPROCESS       CurrentP;
+       PLIST_ENTRY     CurrentEntryT;
+       PETHREAD        CurrentT;
+       
+       ULONG           RequiredSize = 0L;
+       BOOLEAN         SizeOnly = FALSE;
+
+       ULONG           SpiSize = 0L;
+       
+       PSYSTEM_PROCESS_INFORMATION     pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
+       PSYSTEM_PROCESS_INFORMATION     pInfoPLast = NULL;
+       PSYSTEM_THREAD_INFO             pInfoT = NULL;
+       
+
+   /* Lock the process list. */
+   ExAcquireFastMutex(&PspActiveProcessMutex);
+
+       /*
+        * Scan the process list. Since the
+        * list is circular, the guard is false
+        * after the last process.
+        */
+       for (   CurrentEntryP = PsActiveProcessHead.Flink;
+               (CurrentEntryP != & PsActiveProcessHead);
+               CurrentEntryP = CurrentEntryP->Flink
+               )
+       {
+               /*
+                * Compute how much space is
+                * occupied in the snapshot
+                * by adding this process info.
+                * (at least one thread).
+                */
+               SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
+               RequiredSize += SpiSizeCurrent;
+               /*
+                * Do not write process data in the
+                * buffer if it is too small.
+                */
+               if (TRUE == SizeOnly) continue;
+               /*
+                * Check if the buffer can contain
+                * the full snapshot.
+                */
+               if (Size < RequiredSize)
+               {
+                       SizeOnly = TRUE;
+                       continue;
+               }
+               /* 
+                * Get a reference to the 
+                * process descriptor we are
+                * handling.
+                */
+               CurrentP = CONTAINING_RECORD(
+                               CurrentEntryP,
+                               EPROCESS, 
+                               ProcessListEntry
+                               );
+               /*
+                * Write process data in the buffer.
+                */
+               RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
+               /* PROCESS */
+               pInfoP->ThreadCount = 0L;
+               pInfoP->ProcessId = CurrentP->UniqueProcessId;
+               RtlInitUnicodeString (
+                       & pInfoP->Name,
+                       CurrentP->ImageFileName
+                       );
+               /* THREAD */
+               for (   pInfoT = & CurrentP->ThreadSysInfo [0],
+                       CurrentEntryT = CurrentP->ThreadListHead.Flink;
+                       
+                       (CurrentEntryT != & CurrentP->ThreadListHead);
+                       
+                       pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
+                       CurrentEntryT = CurrentEntryT->Flink
+                       )
+               {
+                       /*
+                        * Recalculate the size of the
+                        * information block.
+                        */
+                       if (0 < pInfoP->ThreadCount)
+                       {
+                               RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
+                       }
+                       /*
+                        * Do not write thread data in the
+                        * buffer if it is too small.
+                        */
+                       if (TRUE == SizeOnly) continue;
+                       /*
+                        * Check if the buffer can contain
+                        * the full snapshot.
+                        */
+                       if (Size < RequiredSize)
+                       {
+                               SizeOnly = TRUE;
+                               continue;
+                       }
+                       /* 
+                        * Get a reference to the 
+                        * thread descriptor we are
+                        * handling.
+                        */
+                       CurrentT = CONTAINING_RECORD(
+                                       CurrentEntryT,
+                                       KTHREAD, 
+                                       ThreadListEntry
+                                       );
+                       /*
+                        * Write thread data.
+                        */
+                       RtlZeroMemory (
+                               pInfoT,
+                               sizeof (SYSTEM_THREAD_INFORMATION)
+                               );
+                       pInfoT->KernelTime      = CurrentT-> ;  /* TIME */
+                       pInfoT->UserTime        = CurrentT-> ;  /* TIME */
+                       pInfoT->CreateTime      = CurrentT-> ;  /* TIME */
+                       pInfoT->TickCount       = CurrentT-> ;  /* ULONG */
+                       pInfoT->StartEIP        = CurrentT-> ;  /* ULONG */
+                       pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
+                       pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
+                       pInfoT->DynamicPriority = CurrentT-> ;  /* ULONG */
+                       pInfoT->BasePriority    = CurrentT-> ;  /* ULONG */
+                       pInfoT->nSwitches       = CurrentT-> ;  /* ULONG */
+                       pInfoT->State           = CurrentT-> ;  /* DWORD */
+                       pInfoT->WaitReason      = CurrentT-> ;  /* KWAIT_REASON */
+                       /*
+                        * Count the number of threads 
+                        * this process has.
+                        */
+                       ++ pInfoP->ThreadCount;
+               }
+               /*
+                * Save the size of information
+                * stored in the buffer for the
+                * current process.
+                */
+               pInfoP->RelativeOffset = SpiSize;
+               /*
+                * Save a reference to the last
+                * valid information block.
+                */
+               pInfoPLast = pInfoP;
+               /*
+                * Compute the offset of the 
+                * SYSTEM_PROCESS_INFORMATION
+                * descriptor in the snapshot 
+                * buffer for the next process.
+                */
+               (ULONG) pInfoP += SpiSize;
+       }
+       /*
+        * Unlock the process list.
+        */
+       ExReleaseFastMutex (
+               & PspActiveProcessMutex
+               );
+       /*
+        * Return the proper error status code,
+        * if the buffer was too small.
+        */
+       if (TRUE == SizeOnly)
+       {
+               if (NULL != RequiredSize)
+               {
+                       *pRequiredSize = RequiredSize;
+               }
+               return STATUS_INFO_LENGTH_MISMATCH;
+       }
+       /*
+        * Mark the end of the snapshot.
+        */
+       pInfoP->RelativeOffset = 0L;
+       /* OK */        
+       return STATUS_SUCCESS;
+#endif
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+NtSetInformationThread (IN HANDLE ThreadHandle,
+                       IN THREADINFOCLASS ThreadInformationClass,
+                       IN PVOID ThreadInformation,
+                       IN ULONG ThreadInformationLength)
+{
+  PETHREAD Thread;
+  NTSTATUS Status;
+  union
+  {
+     KPRIORITY Priority;
+     LONG Increment;
+     KAFFINITY Affinity;
+     HANDLE Handle;
+     PVOID Address;
+  }u;
+  
+  PAGED_CODE();
+
+  if (ThreadInformationClass <= MaxThreadInfoClass &&
+      !SetInformationData[ThreadInformationClass].Implemented)
+    {
+      return STATUS_NOT_IMPLEMENTED;
+    }
+  if (ThreadInformationClass > MaxThreadInfoClass ||
+      SetInformationData[ThreadInformationClass].Size == 0)
+    {
+      return STATUS_INVALID_INFO_CLASS;
+    }
+  if (ThreadInformationLength != SetInformationData[ThreadInformationClass].Size)
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  Status = ObReferenceObjectByHandle (ThreadHandle,
+                                     THREAD_SET_INFORMATION,
+                                     PsThreadType,
+                                     ExGetPreviousMode (),
+                                     (PVOID*)&Thread,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+
+   Status = MmCopyFromCaller(&u.Priority,
+                            ThreadInformation,
+                            SetInformationData[ThreadInformationClass].Size);
+   if (NT_SUCCESS(Status))
+     {
+       switch (ThreadInformationClass)
+         {
+           case ThreadPriority:
+            if (u.Priority < LOW_PRIORITY || u.Priority >= MAXIMUM_PRIORITY)
+              {
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+              }
+            KeSetPriorityThread(&Thread->Tcb, u.Priority);
+            break;
+       
+           case ThreadBasePriority:
+            KeSetBasePriorityThread (&Thread->Tcb, u.Increment);
+            break;
+       
+           case ThreadAffinityMask:
+            Status = KeSetAffinityThread(&Thread->Tcb, u.Affinity);
+            break;
+       
+           case ThreadImpersonationToken:
+            Status = PsAssignImpersonationToken (Thread, u.Handle);
+            break;
+               
+           case ThreadQuerySetWin32StartAddress:
+            Thread->Win32StartAddress = u.Address;
+            break;
+
+           default:
+            /* Shoult never occure if the data table is correct */
+            KEBUGCHECK(0);
+        }
+     }
+  ObDereferenceObject (Thread);
+
+  return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtQueryInformationThread (IN   HANDLE          ThreadHandle,
+                         IN    THREADINFOCLASS ThreadInformationClass,
+                         OUT   PVOID           ThreadInformation,
+                         IN    ULONG           ThreadInformationLength,
+                         OUT   PULONG          ReturnLength  OPTIONAL)
+{
+   PETHREAD Thread;
+   NTSTATUS Status;
+   union
+   {
+      THREAD_BASIC_INFORMATION TBI;
+      KERNEL_USER_TIMES TTI;
+      PVOID Address;
+      LARGE_INTEGER Count;
+      BOOLEAN Last;
+   }u;
+   
+   PAGED_CODE();
+
+   if (ThreadInformationClass <= MaxThreadInfoClass &&
+       !QueryInformationData[ThreadInformationClass].Implemented)
+     {
+       return STATUS_NOT_IMPLEMENTED;
+     }
+   if (ThreadInformationClass > MaxThreadInfoClass ||
+       QueryInformationData[ThreadInformationClass].Size == 0)
+     {
+       return STATUS_INVALID_INFO_CLASS;
+     }
+   if (ThreadInformationLength != QueryInformationData[ThreadInformationClass].Size)
+     {
+       return STATUS_INFO_LENGTH_MISMATCH;
+     }
+
+   Status = ObReferenceObjectByHandle(ThreadHandle,
+                                     THREAD_QUERY_INFORMATION,
+                                     PsThreadType,
+                                     ExGetPreviousMode(),
+                                     (PVOID*)&Thread,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+
+   switch (ThreadInformationClass)
+     {
+       case ThreadBasicInformation:
+         /* A test on W2K agains ntdll shows NtQueryInformationThread return STATUS_PENDING
+          * as ExitStatus for current/running thread, while KETHREAD's ExitStatus is 
+          * 0. So do the conversion here:
+          * -Gunnar     */
+         u.TBI.ExitStatus = (Thread->ExitStatus == 0) ? STATUS_PENDING : Thread->ExitStatus;
+        u.TBI.TebBaseAddress = Thread->Tcb.Teb;
+        u.TBI.ClientId = Thread->Cid;
+        u.TBI.AffinityMask = Thread->Tcb.Affinity;
+        u.TBI.Priority = Thread->Tcb.Priority;
+        u.TBI.BasePriority = Thread->Tcb.BasePriority;
+        break;
+       
+       case ThreadTimes:
+        u.TTI.KernelTime.QuadPart = Thread->Tcb.KernelTime * 100000LL;
+         u.TTI.UserTime.QuadPart = Thread->Tcb.UserTime * 100000LL;
+         u.TTI.CreateTime = Thread->CreateTime;
+         /*This works*/
+        u.TTI.ExitTime = Thread->ExitTime;
+         break;
+
+       case ThreadQuerySetWin32StartAddress:
+         u.Address = Thread->Win32StartAddress;
+         break;
+
+       case ThreadPerformanceCount:
+         /* Nebbett says this class is always zero */
+         u.Count.QuadPart = 0;
+         break;
+
+       case ThreadAmILastThread:
+         if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
+            &Thread->ThreadsProcess->ThreadListHead)
+          {
+            u.Last = TRUE;
+          }
+         else
+          {
+            u.Last = FALSE;
+          }
+         break;
+       default:
+        /* Shoult never occure if the data table is correct */
+        KEBUGCHECK(0);
+     }
+   if (QueryInformationData[ThreadInformationClass].Size)
+     {
+       Status = MmCopyToCaller(ThreadInformation,
+                               &u.TBI,
+                              QueryInformationData[ThreadInformationClass].Size);
+     }
+   if (ReturnLength)
+     {
+       NTSTATUS Status2;
+       static ULONG Null = 0;
+       Status2 = MmCopyToCaller(ReturnLength,
+                               NT_SUCCESS(Status) ? &QueryInformationData[ThreadInformationClass].Size : &Null,
+                               sizeof(ULONG));
+       if (NT_SUCCESS(Status))
+         {
+          Status = Status2;
+        }
+     }
+
+   ObDereferenceObject(Thread);
+   return(Status);
+}
+/* EOF */
diff --git a/reactos/ntoskrnl/ps/security.c b/reactos/ntoskrnl/ps/security.c
new file mode 100644 (file)
index 0000000..7c85bd6
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/security.c
+ * PURPOSE:         Process Manager Security (Tokens, Impersionation)
+ *
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* GLOBALS ******************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL 
+NtOpenProcessToken(IN HANDLE ProcessHandle,
+                   IN ACCESS_MASK DesiredAccess,
+                   OUT PHANDLE TokenHandle)
+{
+    return NtOpenProcessTokenEx(ProcessHandle,
+                                DesiredAccess,
+                                0,
+                                TokenHandle);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
+                     IN ACCESS_MASK DesiredAccess,
+                     IN ULONG HandleAttributes,
+                     OUT PHANDLE TokenHandle)
+{
+   PACCESS_TOKEN Token;
+   HANDLE hToken;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   PAGED_CODE();
+   
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(TokenHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = PsOpenTokenOfProcess(ProcessHandle,
+                                &Token);
+   if(NT_SUCCESS(Status))
+   {
+     Status = ObCreateHandle(PsGetCurrentProcess(),
+                            Token,
+                            DesiredAccess,
+                            FALSE,
+                            &hToken);
+     ObDereferenceObject(Token);
+
+     _SEH_TRY
+     {
+       *TokenHandle = hToken;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+   
+   return Status;
+}
+
+/*
+ * @implemented
+ */
+PACCESS_TOKEN 
+STDCALL
+PsReferencePrimaryToken(PEPROCESS Process)
+{
+    /* Reference and return the Token */
+    ObReferenceObjectByPointer(Process->Token,
+                               TOKEN_ALL_ACCESS,
+                               SepTokenObjectType,
+                               KernelMode);
+    return(Process->Token);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+PsOpenTokenOfProcess(HANDLE ProcessHandle,
+                     PACCESS_TOKEN* Token)
+{
+    PEPROCESS Process;
+    NTSTATUS Status;
+   
+    /* Get the Token */
+    Status = ObReferenceObjectByHandle(ProcessHandle,
+                                       PROCESS_QUERY_INFORMATION,
+                                       PsProcessType,
+                                       ExGetPreviousMode(),
+                                       (PVOID*)&Process,
+                                       NULL);
+    
+    /* Reference it */
+    if(NT_SUCCESS(Status)) {
+        
+        *Token = PsReferencePrimaryToken(Process);
+        ObDereferenceObject(Process);
+    }
+   
+    /* Return */
+    return Status;
+}
+
+NTSTATUS
+STDCALL
+PspAssignPrimaryToken(PEPROCESS Process,
+                      HANDLE TokenHandle)
+{
+    PACCESS_TOKEN Token;
+    PACCESS_TOKEN OldToken;
+    NTSTATUS Status;
+   
+    /* Reference the Token */
+    Status = ObReferenceObjectByHandle(TokenHandle,
+                                       0,
+                                       SepTokenObjectType,
+                                       KeGetPreviousMode(),
+                                       (PVOID*)&Token,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) {
+
+        return(Status);
+    }
+    
+    /* Exchange them */
+    Status = SeExchangePrimaryToken(Process, Token, &OldToken);
+        
+    /* Derefernece Tokens and Return */
+    if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken);
+    ObDereferenceObject(Token);
+    return(Status);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+PsAssignImpersonationToken(PETHREAD Thread,
+                           HANDLE TokenHandle)
+{
+    PACCESS_TOKEN Token;
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+    NTSTATUS Status;
+
+    if (TokenHandle != NULL) {
+
+        Status = ObReferenceObjectByHandle(TokenHandle,
+                                           TOKEN_IMPERSONATE,
+                                           SepTokenObjectType,
+                                           KeGetPreviousMode(),
+                                           (PVOID*)&Token,
+                                           NULL);
+        
+        if (!NT_SUCCESS(Status)) {
+            
+            return(Status);
+        }
+        
+        ImpersonationLevel = SeTokenImpersonationLevel(Token);
+    
+    } else {
+        
+        Token = NULL;
+        ImpersonationLevel = 0;
+    }
+
+    PsImpersonateClient(Thread,
+                        Token,
+                        FALSE,
+                        FALSE,
+                        ImpersonationLevel);
+    
+    if (Token != NULL) ObDereferenceObject(Token);
+    return(STATUS_SUCCESS);
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+PsRevertToSelf (VOID)
+{
+    PsRevertThreadToSelf(PsGetCurrentThread());
+}
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+PsRevertThreadToSelf(IN PETHREAD Thread)
+{
+    if (Thread->ActiveImpersonationInfo == TRUE) {
+        
+        ObDereferenceObject (Thread->ImpersonationInfo->Token);
+        Thread->ActiveImpersonationInfo = FALSE;
+    }
+}
+
+/*
+ * @implemented
+ */
+VOID 
+STDCALL
+PsImpersonateClient(IN PETHREAD Thread,
+                    IN PACCESS_TOKEN Token,
+                    IN BOOLEAN CopyOnOpen,
+                    IN BOOLEAN EffectiveOnly,
+                    IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
+{
+    
+    if (Token == NULL) {
+      
+        if (Thread->ActiveImpersonationInfo == TRUE) {
+            
+            Thread->ActiveImpersonationInfo = FALSE;
+            
+            if (Thread->ImpersonationInfo->Token != NULL) {
+                
+                ObDereferenceObject (Thread->ImpersonationInfo->Token);
+            }
+        }
+        
+        return;
+    }
+
+    if (Thread->ImpersonationInfo == NULL) {
+        
+        Thread->ImpersonationInfo = ExAllocatePool(NonPagedPool,
+                                                   sizeof(PS_IMPERSONATION_INFORMATION));
+    }
+
+    Thread->ImpersonationInfo->ImpersonationLevel = ImpersonationLevel;
+    Thread->ImpersonationInfo->CopyOnOpen = CopyOnOpen;
+    Thread->ImpersonationInfo->EffectiveOnly = EffectiveOnly;
+    Thread->ImpersonationInfo->Token = Token;
+    
+    ObReferenceObjectByPointer(Token,
+                               0,
+                               SepTokenObjectType,
+                               KernelMode);
+    
+    Thread->ActiveImpersonationInfo = TRUE;
+}
+
+
+PACCESS_TOKEN
+STDCALL
+PsReferenceEffectiveToken(PETHREAD Thread,
+                          PTOKEN_TYPE TokenType,
+                          PBOOLEAN EffectiveOnly,
+                          PSECURITY_IMPERSONATION_LEVEL Level)
+{
+    PEPROCESS Process;
+    PACCESS_TOKEN Token;
+   
+    if (Thread->ActiveImpersonationInfo == FALSE) {
+        
+        Process = Thread->ThreadsProcess;
+        *TokenType = TokenPrimary;
+        *EffectiveOnly = FALSE;
+        Token = Process->Token;
+    
+    } else {
+
+        Token = Thread->ImpersonationInfo->Token;
+        *TokenType = TokenImpersonation;
+        *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
+        *Level = Thread->ImpersonationInfo->ImpersonationLevel;
+    }
+    
+    return(Token);
+}
+
+NTSTATUS 
+STDCALL
+NtImpersonateThread(IN HANDLE ThreadHandle,
+                    IN HANDLE ThreadToImpersonateHandle,
+                    IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
+{
+  SECURITY_QUALITY_OF_SERVICE SafeServiceQoS;
+  SECURITY_CLIENT_CONTEXT ClientContext;
+  PETHREAD Thread;
+  PETHREAD ThreadToImpersonate;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
+  
+  PAGED_CODE();
+  
+  PreviousMode = ExGetPreviousMode();
+  
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
+    {
+      ProbeForRead(SecurityQualityOfService,
+                   sizeof(SECURITY_QUALITY_OF_SERVICE),
+                   sizeof(ULONG));
+      SafeServiceQoS = *SecurityQualityOfService;
+      SecurityQualityOfService = &SafeServiceQoS;
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    
+    if(!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  }
+
+  Status = ObReferenceObjectByHandle(ThreadHandle,
+                                    THREAD_IMPERSONATE,
+                                    PsThreadType,
+                                    PreviousMode,
+                                    (PVOID*)&Thread,
+                                    NULL);
+  if(NT_SUCCESS(Status))
+  {
+    Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
+                                      THREAD_DIRECT_IMPERSONATION,
+                                      PsThreadType,
+                                      PreviousMode,
+                                      (PVOID*)&ThreadToImpersonate,
+                                      NULL);
+    if(NT_SUCCESS(Status))
+    {
+      Status = SeCreateClientSecurity(ThreadToImpersonate,
+                                     SecurityQualityOfService,
+                                     0,
+                                    &ClientContext);
+      if(NT_SUCCESS(Status))
+      {
+        SeImpersonateClient(&ClientContext,
+                           Thread);
+        if(ClientContext.ClientToken != NULL)
+        {
+          ObDereferenceObject (ClientContext.ClientToken);
+        }
+      }
+
+      ObDereferenceObject(ThreadToImpersonate);
+    }
+    ObDereferenceObject(Thread);
+  }
+
+  return Status;
+}
+
+/*
+ * @implemented
+ */
+PACCESS_TOKEN 
+STDCALL
+PsReferenceImpersonationToken(IN PETHREAD Thread,
+                              OUT PBOOLEAN CopyOnOpen,
+                              OUT PBOOLEAN EffectiveOnly,
+                              OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
+{
+    
+    if (Thread->ActiveImpersonationInfo == FALSE) {
+        
+        return NULL;
+    }
+
+    *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
+    *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
+    *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
+    
+    ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token,
+                               TOKEN_ALL_ACCESS,
+                               SepTokenObjectType,
+                               KernelMode);
+
+    return Thread->ImpersonationInfo->Token;
+}
+
+#ifdef PsDereferencePrimaryToken
+#undef PsDereferenceImpersonationToken
+#endif
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
+{
+    if (ImpersonationToken) {
+        
+        ObDereferenceObject(ImpersonationToken);
+    }
+}
+
+#ifdef PsDereferencePrimaryToken
+#undef PsDereferencePrimaryToken
+#endif
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
+{
+    ObDereferenceObject(PrimaryToken);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+STDCALL
+PsDisableImpersonation(IN PETHREAD Thread,
+                       IN PSE_IMPERSONATION_STATE ImpersonationState)
+{
+    if (Thread->ActiveImpersonationInfo == FALSE) {
+        ImpersonationState->Token = NULL;
+        ImpersonationState->CopyOnOpen = FALSE;
+        ImpersonationState->EffectiveOnly = FALSE;
+        ImpersonationState->Level = 0;
+        return TRUE;
+    }
+
+/* FIXME */
+/*   ExfAcquirePushLockExclusive(&Thread->ThreadLock); */
+
+    Thread->ActiveImpersonationInfo = FALSE;
+    ImpersonationState->Token = Thread->ImpersonationInfo->Token;
+    ImpersonationState->CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
+    ImpersonationState->EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
+    ImpersonationState->Level = Thread->ImpersonationInfo->ImpersonationLevel;
+
+/* FIXME */
+/*   ExfReleasePushLock(&Thread->ThreadLock); */
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */                       
+VOID
+STDCALL
+PsRestoreImpersonation(IN PETHREAD Thread,
+                       IN PSE_IMPERSONATION_STATE ImpersonationState)
+{
+    
+    PsImpersonateClient(Thread, 
+                        ImpersonationState->Token,
+                        ImpersonationState->CopyOnOpen,
+                        ImpersonationState->EffectiveOnly,
+                        ImpersonationState->Level);
+    
+    ObfDereferenceObject(ImpersonationState->Token);
+}
+
+/* EOF */
index 7e1d56e..3c2da35 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
-/* NOTES **********************************************************************
- *
- */
-
-/* GLOBALS *******************************************************************/
-
-static FAST_MUTEX SuspendMutex;
+ULONG
+STDCALL
+KeResumeThread(PKTHREAD Thread);
 
+ULONG
+STDCALL
+KeSuspendThread(PKTHREAD Thread);
 /* FUNCTIONS *****************************************************************/
 
-VOID STDCALL
-PiSuspendThreadRundownRoutine(PKAPC Apc)
-{
-}
-
-
-VOID STDCALL
-PiSuspendThreadKernelRoutine(PKAPC Apc,
-                            PKNORMAL_ROUTINE* NormalRoutine,
-                            PVOID* NormalContext,
-                            PVOID* SystemArgument1,
-                            PVOID* SystemArguemnt2)
-{
-}
-
-
-VOID STDCALL
-PiSuspendThreadNormalRoutine(PVOID NormalContext,
-                            PVOID SystemArgument1,
-                            PVOID SystemArgument2)
-{
-  PETHREAD CurrentThread = PsGetCurrentThread();
-  while (CurrentThread->Tcb.SuspendCount > 0)
-    {
-      KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore,
-                           0,
-                           UserMode,
-                           TRUE,
-                           NULL);
-    }
-}
-
-
-NTSTATUS
-PsResumeThread (PETHREAD Thread,
-               PULONG SuspendCount)
-{
-  DPRINT("PsResumeThread (Thread %p  SuspendCount %p) called\n");
-
-  ExAcquireFastMutex (&SuspendMutex);
-
-  if (SuspendCount != NULL)
-    {
-      *SuspendCount = Thread->Tcb.SuspendCount;
-    }
-
-  if (Thread->Tcb.SuspendCount > 0)
-    {
-      Thread->Tcb.SuspendCount--;
-      if (Thread->Tcb.SuspendCount == 0)
-       {
-         KeReleaseSemaphore (&Thread->Tcb.SuspendSemaphore,
-                             IO_NO_INCREMENT,
-                             1,
-                             FALSE);
-       }
-    }
-
-  ExReleaseFastMutex (&SuspendMutex);
-
-  return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
-{
-  ULONG OldValue;
-
-  ExAcquireFastMutex(&SuspendMutex);
-  OldValue = Thread->Tcb.SuspendCount;
-  Thread->Tcb.SuspendCount++;
-  if (!Thread->Tcb.SuspendApc.Inserted)
-    {
-      if (!KeInsertQueueApc(&Thread->Tcb.SuspendApc,
-                           NULL,
-                           NULL,
-                           IO_NO_INCREMENT))
-       {
-         Thread->Tcb.SuspendCount--;
-         ExReleaseFastMutex(&SuspendMutex);
-         return(STATUS_THREAD_IS_TERMINATING);
-       }
-    }
-  ExReleaseFastMutex(&SuspendMutex);
-  if (PreviousSuspendCount != NULL)
-    {
-      *PreviousSuspendCount = OldValue;
-    }
-  return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS STDCALL
-NtResumeThread(IN HANDLE ThreadHandle,
-              IN PULONG SuspendCount  OPTIONAL)
 /*
  * FUNCTION: Decrements a thread's resume count
  * ARGUMENTS: 
@@ -127,48 +30,39 @@ NtResumeThread(IN HANDLE ThreadHandle,
  *        ResumeCount =  The resulting resume count.
  * RETURNS: Status
  */
+NTSTATUS
+STDCALL
+NtResumeThread(IN HANDLE ThreadHandle,
+               IN PULONG SuspendCount  OPTIONAL)
 {
-  PETHREAD Thread;
-  NTSTATUS Status;
-  ULONG Count;
+    PETHREAD Thread;
+    NTSTATUS Status;
   
-  PAGED_CODE();
-
-  DPRINT("NtResumeThead(ThreadHandle %lx  SuspendCount %p)\n",
-        ThreadHandle, SuspendCount);
-
-  Status = ObReferenceObjectByHandle (ThreadHandle,
-                                     THREAD_SUSPEND_RESUME,
-                                     PsThreadType,
-                                     UserMode,
-                                     (PVOID*)&Thread,
-                                     NULL);
-  if (!NT_SUCCESS(Status))
-    {
-      return Status;
+    PAGED_CODE();
+
+    DPRINT1("NtResumeThead(ThreadHandle %lx  SuspendCount %p)\n",
+            ThreadHandle, SuspendCount);
+
+    /* Get the Thread Object */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_SUSPEND_RESUME,
+                                       PsThreadType,
+                                       KeGetPreviousMode(),
+                                       (PVOID*)&Thread,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) {
+        
+        return Status;
     }
+    
+    /* Call the Kernel Function */
+    *SuspendCount = KeResumeThread(&Thread->Tcb);
 
-  Status = PsResumeThread (Thread, &Count);
-  if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject ((PVOID)Thread);
-      return Status;
-    }
-
-  if (SuspendCount != NULL)
-    {
-      *SuspendCount = Count;
-    }
-
-  ObDereferenceObject ((PVOID)Thread);
-
-  return STATUS_SUCCESS;
+    /* Dereference and Return */
+    ObDereferenceObject ((PVOID)Thread);
+    return STATUS_SUCCESS;
 }
 
-
-NTSTATUS STDCALL
-NtSuspendThread(IN HANDLE ThreadHandle,
-               IN PULONG PreviousSuspendCount  OPTIONAL)
 /*
  * FUNCTION: Increments a thread's suspend count
  * ARGUMENTS: 
@@ -182,45 +76,34 @@ NtSuspendThread(IN HANDLE ThreadHandle,
  *        MAXIMUM_SUSPEND_COUNT.
  * RETURNS: Status
  */
+NTSTATUS 
+STDCALL
+NtSuspendThread(IN HANDLE ThreadHandle,
+                IN PULONG PreviousSuspendCount  OPTIONAL)
 {
-  PETHREAD Thread;
-  NTSTATUS Status;
-  ULONG Count;
+    PETHREAD Thread;
+    NTSTATUS Status;
   
-  PAGED_CODE();
-
-  Status = ObReferenceObjectByHandle(ThreadHandle,
-                                    THREAD_SUSPEND_RESUME,
-                                    PsThreadType,
-                                    UserMode,
-                                    (PVOID*)&Thread,
-                                    NULL);
-  if (!NT_SUCCESS(Status))
-    {
-      return(Status);
-    }
-
-  Status = PsSuspendThread(Thread, &Count);
-  if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject ((PVOID)Thread);
-      return Status;
-    }
-
-  if (PreviousSuspendCount != NULL)
-    {
-      *PreviousSuspendCount = Count;
+    PAGED_CODE();
+
+    /* Get the Thread Object */
+    Status = ObReferenceObjectByHandle(ThreadHandle,
+                                       THREAD_SUSPEND_RESUME,
+                                       PsThreadType,
+                                       KeGetPreviousMode(),
+                                       (PVOID*)&Thread,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) {
+        
+        return Status;
     }
+    
+    /* Call the Kernel Function */
+    *PreviousSuspendCount = KeSuspendThread(&Thread->Tcb);
 
-  ObDereferenceObject ((PVOID)Thread);
-
-  return STATUS_SUCCESS;
-}
-
-VOID INIT_FUNCTION
-PsInitialiseSuspendImplementation(VOID)
-{
-  ExInitializeFastMutex(&SuspendMutex);
+    /* Dereference and Return */
+    ObDereferenceObject((PVOID)Thread);
+    return STATUS_SUCCESS;
 }
 
 /* EOF */
index 08a0a10..e91b589 100644 (file)
@@ -23,8 +23,6 @@
 #define NDEBUG
 #include <internal/debug.h>
 
-/* TYPES *******************************************************************/
-
 /* GLOBALS ******************************************************************/
 
 extern LIST_ENTRY PsActiveProcessHead;
@@ -32,20 +30,12 @@ extern PEPROCESS PsIdleProcess;
 
 POBJECT_TYPE EXPORTED PsThreadType = NULL;
 
-LONG PiNrThreadsAwaitingReaping = 0;
-
 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
+extern ULONG IdleProcessorMask;
+extern LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
 
-/*
- * PURPOSE: List of threads associated with each priority level
- */
-static LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
-static ULONG PriorityListMask = 0;
-static ULONG IdleProcessorMask = 0;
-static BOOLEAN DoneInitYet = FALSE;
-static KEVENT PiReaperThreadEvent;
-static BOOLEAN PiReaperThreadShouldTerminate = FALSE;
 
+BOOLEAN DoneInitYet = FALSE;
 static GENERIC_MAPPING PiThreadMapping = {STANDARD_RIGHTS_READ | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,
                                          STANDARD_RIGHTS_WRITE | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_ALERT |
                       THREAD_SET_INFORMATION | THREAD_SET_CONTEXT,
@@ -222,16 +212,13 @@ PsIsThreadTerminating(IN PETHREAD Thread)
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 STDCALL
-PsIsSystemThread(
-    PETHREAD Thread
-    )
+PsIsSystemThread(PETHREAD Thread)
 {
-       UNIMPLEMENTED;
-       return FALSE;   
+    return (Thread->SystemThread ? TRUE: FALSE);
 }
 
 /*
@@ -246,41 +233,6 @@ PsIsThreadImpersonating(
   return Thread->ActiveImpersonationInfo;
 }
 
-static VOID
-KiRequestReschedule(CCHAR Processor)
-{
-   PKPCR Pcr;
-
-   Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
-   Pcr->Prcb->QuantumEnd = TRUE;
-   KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
-}
-
-static VOID
-PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
-{
-   ASSERT(THREAD_STATE_READY == Thread->Tcb.State);
-   ASSERT(Thread->Tcb.Priority == Priority);
-   if (Priority >= MAXIMUM_PRIORITY || Priority < LOW_PRIORITY)
-     {
-       DPRINT1("Invalid thread priority (%d)\n", Priority);
-       KEBUGCHECK(0);
-     }
-   InsertTailList(&PriorityListHead[Priority], &Thread->Tcb.QueueListEntry);
-   PriorityListMask |= (1 << Priority);
-}
-
-static VOID PsRemoveFromThreadList(PETHREAD Thread)
-{
-   ASSERT(THREAD_STATE_READY == Thread->Tcb.State);
-   RemoveEntryList(&Thread->Tcb.QueueListEntry);
-   if (IsListEmpty(&PriorityListHead[(ULONG)Thread->Tcb.Priority]))
-     {
-        PriorityListMask &= ~(1 << Thread->Tcb.Priority);
-     }
-}
-
-
 VOID PsDumpThreads(BOOLEAN IncludeSystem)
 {
    PLIST_ENTRY AThread, AProcess;
@@ -335,259 +287,6 @@ VOID PsDumpThreads(BOOLEAN IncludeSystem)
    }
 }
 
-static PETHREAD PsScanThreadList(KPRIORITY Priority, ULONG Affinity)
-{
-   PLIST_ENTRY current_entry;
-   PETHREAD current;
-   ULONG Mask;
-
-   Mask = (1 << Priority);
-   if (PriorityListMask & Mask)
-     {
-       current_entry = PriorityListHead[Priority].Flink;
-       while (current_entry != &PriorityListHead[Priority])
-         {
-           current = CONTAINING_RECORD(current_entry, ETHREAD,
-                                      Tcb.QueueListEntry);
-          if (current->Tcb.State != THREAD_STATE_READY)
-            {
-              DPRINT1("%d/%d\n", current->Cid.UniqueThread, current->Tcb.State);
-            }
-           ASSERT(current->Tcb.State == THREAD_STATE_READY);
-           DPRINT("current->Tcb.Affinity %x Affinity %x PID %d %d\n",
-                 current->Tcb.Affinity, Affinity, current->Cid.UniqueThread,
-                 Priority);
-           if (current->Tcb.Affinity & Affinity)
-            {
-              PsRemoveFromThreadList(current);
-              return(current);
-            }
-           current_entry = current_entry->Flink;
-        }
-     }
-   return(NULL);
-}
-
-VOID STDCALL
-PiWakeupReaperThread(VOID)
-{
-  KeSetEvent(&PiReaperThreadEvent, 0, FALSE);
-}
-
-VOID STDCALL
-PiReaperThreadMain(PVOID Ignored)
-{
-  for(;;)
-  {
-    KeWaitForSingleObject(&PiReaperThreadEvent,
-                         Executive,
-                         KernelMode,
-                         FALSE,
-                         NULL);
-    if (PiReaperThreadShouldTerminate)
-       {
-         PsTerminateSystemThread(0);
-       }
-    PsReapThreads();
-  }
-}
-
-VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
-{
-   KPRIORITY CurrentPriority;
-   PETHREAD Candidate;
-   ULONG Affinity;
-   PKTHREAD KCurrentThread = KeGetCurrentThread();
-   PETHREAD CurrentThread = CONTAINING_RECORD(KCurrentThread, ETHREAD, Tcb);
-
-   DPRINT("PsDispatchThread() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(),
-          CurrentThread->Cid.UniqueThread, NewThreadStatus, CurrentThread->Tcb.State);
-
-   CurrentThread->Tcb.State = (UCHAR)NewThreadStatus;
-   switch(NewThreadStatus)
-   {
-     case THREAD_STATE_READY:
-       PsInsertIntoThreadList(CurrentThread->Tcb.Priority,
-                              CurrentThread);
-       break;
-     case THREAD_STATE_TERMINATED_1:
-       PsQueueThreadReap(CurrentThread);
-       break;
-   }
-
-   Affinity = 1 << KeGetCurrentProcessorNumber();
-   for (CurrentPriority = HIGH_PRIORITY;
-       CurrentPriority >= LOW_PRIORITY;
-       CurrentPriority--)
-     {
-       Candidate = PsScanThreadList(CurrentPriority, Affinity);
-       if (Candidate == CurrentThread)
-         {
-            Candidate->Tcb.State = THREAD_STATE_RUNNING;
-            KeReleaseDispatcherDatabaseLockFromDpcLevel();     
-            return;
-         }
-       if (Candidate != NULL)
-         {
-           PETHREAD OldThread;
-           PKTHREAD IdleThread;
-
-           DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority);
-
-           Candidate->Tcb.State = THREAD_STATE_RUNNING;
-
-           OldThread = CurrentThread;
-           CurrentThread = Candidate;
-           IdleThread = KeGetCurrentPrcb()->IdleThread;
-
-           if (&OldThread->Tcb == IdleThread)
-           {
-              IdleProcessorMask &= ~Affinity;
-           }
-           else if (&CurrentThread->Tcb == IdleThread)
-           {
-              IdleProcessorMask |= Affinity;
-           }
-
-           MmUpdatePageDir(PsGetCurrentProcess(),(PVOID)CurrentThread->ThreadsProcess, sizeof(EPROCESS));
-
-           KiArchContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
-           return;
-         }
-     }
-   CPRINT("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber());
-   PsDumpThreads(TRUE);
-   KEBUGCHECK(0);
-}
-
-VOID STDCALL
-PsDispatchThread(ULONG NewThreadStatus)
-{
-   KIRQL oldIrql;
-
-   if (!DoneInitYet || KeGetCurrentPrcb()->IdleThread == NULL)
-     {
-       return;
-     }
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-   PsDispatchThreadNoLock(NewThreadStatus);
-   KeLowerIrql(oldIrql);
-}
-
-VOID
-PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment)
-{
-  if (THREAD_STATE_TERMINATED_1 == Thread->Tcb.State ||
-      THREAD_STATE_TERMINATED_2 == Thread->Tcb.State)
-    {
-       DPRINT("Can't unblock thread %d because it's terminating\n",
-              Thread->Cid.UniqueThread);
-    }
-  else if (THREAD_STATE_READY == Thread->Tcb.State ||
-           THREAD_STATE_RUNNING == Thread->Tcb.State)
-    {
-       DPRINT("Can't unblock thread %d because it's ready or running\n",
-              Thread->Cid.UniqueThread);
-    }
-  else
-    {
-      ULONG Processor;
-      KAFFINITY Affinity;
-
-      /* FIXME: This propably isn't the right way to do it... */
-      if (Thread->Tcb.Priority < LOW_REALTIME_PRIORITY &&
-          Thread->Tcb.BasePriority < LOW_REALTIME_PRIORITY - 2)
-        {
-          if (!Thread->Tcb.PriorityDecrement && !Thread->Tcb.DisableBoost)
-            {
-              Thread->Tcb.Priority = Thread->Tcb.BasePriority + Increment;
-              Thread->Tcb.PriorityDecrement = Increment;
-            }
-        }
-      else
-        {
-          Thread->Tcb.Quantum = Thread->Tcb.ApcState.Process->ThreadQuantum;
-        }
-     
-      if (WaitStatus != NULL)
-       {
-         Thread->Tcb.WaitStatus = *WaitStatus;
-       }
-      Thread->Tcb.State = THREAD_STATE_READY;
-      PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
-      Processor = KeGetCurrentProcessorNumber();
-      Affinity = Thread->Tcb.Affinity;
-      if (!(IdleProcessorMask & (1 << Processor) & Affinity) &&
-          (IdleProcessorMask & ~(1 << Processor) & Affinity))
-        {
-         ULONG i;
-         for (i = 0; i < KeNumberProcessors - 1; i++)
-           {
-             Processor++;
-             if (Processor >= KeNumberProcessors)
-               {
-                 Processor = 0;
-               }
-             if (IdleProcessorMask & (1 << Processor) & Affinity)
-               {
-#if 0          
-                  /* FIXME:
-                   *   Reschedule the threads on an other processor 
-                   */
-                 KeReleaseDispatcherDatabaseLockFromDpcLevel();
-                  KiRequestReschedule(Processor);
-                 KeAcquireDispatcherDatabaseLockAtDpcLevel();
-#endif
-                 break;
-               }
-           }
-       } 
-    }
-}
-
-VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status, 
-              UCHAR Alertable, 
-              ULONG WaitMode,
-              UCHAR WaitReason)
-{
-    PKTHREAD Thread = KeGetCurrentThread();
-    PKWAIT_BLOCK WaitBlock;
-
-    if (Thread->ApcState.KernelApcPending) {
-    
-        DPRINT("Dispatching Thread as ready (APC!)\n");
-        
-        /* Remove Waits */
-        WaitBlock = Thread->WaitBlockList;
-        while (WaitBlock) {
-            RemoveEntryList (&WaitBlock->WaitListEntry);
-            WaitBlock = WaitBlock->NextWaitBlock;
-        }
-        Thread->WaitBlockList = NULL;
-        
-        /* Dispatch it and return status */
-        PsDispatchThreadNoLock (THREAD_STATE_READY);
-        if (Status != NULL) *Status = STATUS_KERNEL_APC;
-
-    } else {
-
-        /* Set the Thread Data as Requested */
-        DPRINT("Dispatching Thread as blocked\n");
-        Thread->Alertable = Alertable;
-        Thread->WaitMode = (UCHAR)WaitMode;
-        Thread->WaitReason = WaitReason;
-        
-        /* Dispatch it and return status */
-        PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
-        if (Status != NULL) *Status = Thread->WaitStatus;
-    }
-    
-    DPRINT("Releasing Dispatcher Lock\n");
-    KfLowerIrql(Thread->WaitIrql);
-}
-
 VOID
 PsFreezeAllThreads(PEPROCESS Process)
      /*
@@ -751,7 +450,7 @@ PsInitThreadManagment(VOID)
    PsThreadType->Dump = NULL;
    PsThreadType->Open = NULL;
    PsThreadType->Close = NULL;
-   PsThreadType->Delete = PiDeleteThread;
+   PsThreadType->Delete = PspDeleteThread;
    PsThreadType->Parse = NULL;
    PsThreadType->Security = NULL;
    PsThreadType->QueryName = NULL;
@@ -773,219 +472,11 @@ PsInitThreadManagment(VOID)
    DPRINT("FirstThread %x\n",FirstThread);
 
    DoneInitYet = TRUE;
-}
-
-VOID
-PsInitReaperThread(VOID)
-{
-   PETHREAD ReaperThread;
-   KIRQL oldIrql;
-   NTSTATUS Status;
    
-   /*
-    * Create the reaper thread
-    */
-   PsInitializeThreadReaper();
-   KeInitializeEvent(&PiReaperThreadEvent, SynchronizationEvent, FALSE);
-   Status = PsInitializeThread(NULL,
-                              &ReaperThread,
-                              NULL,
-                              KernelMode,
-                              FALSE);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("PS: Failed to create reaper thread.\n");
-       KEBUGCHECK(0);
-     }
-
-   ReaperThread->StartAddress = PiReaperThreadMain;
-   Status = KiArchInitThread(&ReaperThread->Tcb, PiReaperThreadMain, NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("PS: Failed to initialize reaper thread.\n");
-       KEBUGCHECK(0);
-     }
-
-   oldIrql = KeAcquireDispatcherDatabaseLock ();
-   PsUnblockThread(ReaperThread, NULL, 0);
-   KeReleaseDispatcherDatabaseLock(oldIrql);
-}
-
-/*
- * @implemented
- */
-LONG STDCALL
-KeSetBasePriorityThread (PKTHREAD      Thread,
-                        LONG           Increment)
-/*
- * Sets thread's base priority relative to the process' base priority
- * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
- */
-{
-   KPRIORITY Priority;
-   if (Increment < -2)
-     {
-       Increment = -2;
-     }
-   else if (Increment > 2)
-     {
-       Increment = 2;
-     }
-   Priority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
-   if (Priority < LOW_PRIORITY)
-   {
-     Priority = LOW_PRIORITY;
-   }
-   else if (Priority >= MAXIMUM_PRIORITY)
-     {
-       Thread->BasePriority = HIGH_PRIORITY;
-     }
-   KeSetPriorityThread(Thread, Priority);
-   return 1;
-}
-
-
-/*
- * @implemented
- */
-KPRIORITY STDCALL
-KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority)
-{
-   KPRIORITY OldPriority;
-   KIRQL oldIrql;
-   PKTHREAD CurrentThread;
-   ULONG Mask;
-   int i;
-   PKPCR Pcr;
-
-   if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY)
-     {
-       KEBUGCHECK(0);
-     }
-
-   oldIrql = KeAcquireDispatcherDatabaseLock();
-
-   OldPriority = Thread->Priority;
-
-   if (OldPriority != Priority)
-     {
-       CurrentThread = KeGetCurrentThread();
-       if (Thread->State == THREAD_STATE_READY)
-         {
-          PsRemoveFromThreadList((PETHREAD)Thread);
-           Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-          PsInsertIntoThreadList(Priority, (PETHREAD)Thread);
-          if (CurrentThread->Priority < Priority)
-            {
-               PsDispatchThreadNoLock(THREAD_STATE_READY);
-               KeLowerIrql(oldIrql);
-              return (OldPriority);
-            }
-        }
-       else if (Thread->State == THREAD_STATE_RUNNING)
-         {
-           Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-          if (Priority < OldPriority)
-            {
-              /* Check for threads with a higher priority */
-              Mask = ~((1 << (Priority + 1)) - 1);
-              if (PriorityListMask & Mask)
-                {
-                  if (Thread == CurrentThread)
-                    {
-                       PsDispatchThreadNoLock(THREAD_STATE_READY);
-                       KeLowerIrql(oldIrql);
-                      return (OldPriority);
-                    }
-                  else
-                    {
-                      for (i = 0; i < KeNumberProcessors; i++)
-                      {
-                         Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-                         if (Pcr->Prcb->CurrentThread == Thread)
-                         {
-                           KeReleaseDispatcherDatabaseLockFromDpcLevel();
-                            KiRequestReschedule(i);
-                            KeLowerIrql(oldIrql);
-                           return (OldPriority);
-                         }
-                      }
-                    }
-                }
-            }
-        }
-       else
-         {
-            Thread->BasePriority = Thread->Priority = (CHAR)Priority;
-         }
-     }
-   KeReleaseDispatcherDatabaseLock(oldIrql);
-   return(OldPriority);
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-KeSetAffinityThread(PKTHREAD   Thread,
-                   KAFFINITY   Affinity)
-/*
- * Sets thread's affinity
- */
-{
-    KIRQL oldIrql;
-    ULONG i;
-    PKPCR Pcr;
-    KAFFINITY ProcessorMask;
-
-    DPRINT("KeSetAffinityThread(Thread %x, Affinity %x)\n", Thread, Affinity);
-
-    ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
-
-    oldIrql = KeAcquireDispatcherDatabaseLock();
-
-    Thread->UserAffinity = Affinity;
-    if (Thread->SystemAffinityActive == FALSE)
-    {
-       Thread->Affinity = Affinity;
-       if (Thread->State == THREAD_STATE_RUNNING)
-       {
-          ProcessorMask = 1 << KeGetCurrentKPCR()->ProcessorNumber;
-          if (Thread == KeGetCurrentThread())
-         {
-            if (!(Affinity & ProcessorMask))
-            {
-                PsDispatchThreadNoLock(THREAD_STATE_READY);
-                KeLowerIrql(oldIrql);
-               return STATUS_SUCCESS;
-            }
-         }
-         else
-         {
-            for (i = 0; i < KeNumberProcessors; i++)
-            {
-               Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-               if (Pcr->Prcb->CurrentThread == Thread)
-               {
-                  if (!(Affinity & ProcessorMask))
-                  {
-                     KeReleaseDispatcherDatabaseLockFromDpcLevel();
-                      KiRequestReschedule(i);
-                      KeLowerIrql(oldIrql);
-                     return STATUS_SUCCESS;
-                  }
-                  break;
-               }
-            }
-            ASSERT (i < KeNumberProcessors);
-         }
-       }
-    }
-    KeReleaseDispatcherDatabaseLock(oldIrql);
-    return STATUS_SUCCESS;
+   InitializeListHead(&PspReaperListHead);
+   ExInitializeWorkItem(&PspReaperWorkItem, PspReapRoutine, NULL);
 }
 
-
 /**********************************************************************
  *     NtOpenThread/4
  *
@@ -1088,7 +579,7 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
 NTSTATUS STDCALL
 NtYieldExecution(VOID)
 {
-  PsDispatchThread(THREAD_STATE_READY);
+  KiDispatchThread(THREAD_STATE_READY);
   return(STATUS_SUCCESS);
 }
 
@@ -1103,68 +594,30 @@ NtTestAlert(VOID)
   return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
 }
 
+VOID
+KeSetPreviousMode (ULONG Mode)
+{
+  PsGetCurrentThread()->Tcb.PreviousMode = (UCHAR)Mode;
+}
+
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
-                          OUT PEPROCESS *Process OPTIONAL,
-                          OUT PETHREAD *Thread)
+KPROCESSOR_MODE STDCALL
+KeGetPreviousMode (VOID)
 {
-  PHANDLE_TABLE_ENTRY CidEntry;
-  PETHREAD FoundThread;
-
-  PAGED_CODE();
-
-  ASSERT(Thread);
-  ASSERT(Cid);
-
-  CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
-  if(CidEntry != NULL)
-  {
-    ObReferenceObject(FoundThread);
-
-    PsUnlockCidHandle(CidEntry);
-
-    if(Process != NULL)
-    {
-      *Process = FoundThread->ThreadsProcess;
-    }
-    *Thread = FoundThread;
-    return STATUS_SUCCESS;
-  }
-
-  return STATUS_INVALID_PARAMETER;
+  return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
-PsLookupThreadByThreadId(IN HANDLE ThreadId,
-                        OUT PETHREAD *Thread)
+KPROCESSOR_MODE STDCALL
+ExGetPreviousMode (VOID)
 {
-  PHANDLE_TABLE_ENTRY CidEntry;
-  PETHREAD FoundThread;
-
-  PAGED_CODE();
-
-  ASSERT(Thread);
-
-  CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
-  if(CidEntry != NULL)
-  {
-    ObReferenceObject(FoundThread);
-
-    PsUnlockCidHandle(CidEntry);
-
-    *Thread = FoundThread;
-    return STATUS_SUCCESS;
-  }
-
-  return STATUS_INVALID_PARAMETER;
+  return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode;
 }
 
 /* EOF */
diff --git a/reactos/ntoskrnl/ps/tinfo.c b/reactos/ntoskrnl/ps/tinfo.c
deleted file mode 100644 (file)
index c9ca051..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ps/tinfo.c
- * PURPOSE:         Getting/setting thread information
- * 
- * PROGRAMMERS:     David Welch (welch@mcmail.com)
- *                  Skywing (skywing@valhallalegends.com)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#include <internal/debug.h>
-
-/* GLOBALS *****************************************************************/
-
-/*
- * FIXME:
- *   Remove the Implemented value if all functions are implemented.
- */
-
-static const struct
-{
-   BOOLEAN Implemented;
-   ULONG Size;
-} QueryInformationData[MaxThreadInfoClass + 1] = 
-{
-    {TRUE, sizeof(THREAD_BASIC_INFORMATION)},  // ThreadBasicInformation
-    {TRUE, sizeof(KERNEL_USER_TIMES)},         // ThreadTimes
-    {TRUE, 0},                                 // ThreadPriority
-    {TRUE, 0},                                 // ThreadBasePriority
-    {TRUE, 0},                                 // ThreadAffinityMask
-    {TRUE, 0},                                 // ThreadImpersonationToken
-    {FALSE, 0},                                        // ThreadDescriptorTableEntry
-    {TRUE, 0},                                 // ThreadEnableAlignmentFaultFixup
-    {TRUE, 0},                                 // ThreadEventPair
-    {TRUE, sizeof(PVOID)},                     // ThreadQuerySetWin32StartAddress
-    {TRUE, 0},                                 // ThreadZeroTlsCell
-    {TRUE, sizeof(LARGE_INTEGER)},             // ThreadPerformanceCount
-    {TRUE, sizeof(BOOLEAN)},                   // ThreadAmILastThread
-    {TRUE, 0},                                 // ThreadIdealProcessor
-    {FALSE, 0},                                        // ThreadPriorityBoost
-    {TRUE, 0},                                 // ThreadSetTlsArrayAddress
-    {FALSE, 0},                                        // ThreadIsIoPending
-    {TRUE, 0}                                  // ThreadHideFromDebugger
-};
-
-static const struct
-{
-   BOOLEAN Implemented;
-   ULONG Size;
-} SetInformationData[MaxThreadInfoClass + 1] = 
-{
-    {TRUE, 0},                 // ThreadBasicInformation
-    {TRUE, 0},                 // ThreadTimes
-    {TRUE, sizeof(KPRIORITY)}, // ThreadPriority
-    {TRUE, sizeof(LONG)},      // ThreadBasePriority
-    {TRUE, sizeof(KAFFINITY)}, // ThreadAffinityMask
-    {TRUE, sizeof(HANDLE)},    // ThreadImpersonationToken
-    {TRUE, 0},                 // ThreadDescriptorTableEntry
-    {FALSE, 0},                        // ThreadEnableAlignmentFaultFixup
-#ifdef _ENABLE_THRDEVTPAIR
-    {TRUE, sizeof(HANDLE)},    // ThreadEventPair
-#else
-    {FALSE, 0},                        // ThreadEventPair
-#endif
-    {TRUE, sizeof(PVOID)},     // ThreadQuerySetWin32StartAddress
-    {FALSE, 0},                        // ThreadZeroTlsCell
-    {TRUE, 0},                 // ThreadPerformanceCount
-    {TRUE, 0},                 // ThreadAmILastThread
-    {FALSE, 0},                        // ThreadIdealProcessor
-    {FALSE, 0},                        // ThreadPriorityBoost
-    {FALSE, 0},                        // ThreadSetTlsArrayAddress
-    {TRUE, 0},                 // ThreadIsIoPending
-    {FALSE, 0}                 // ThreadHideFromDebugger
-};
-
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-NtSetInformationThread (IN HANDLE ThreadHandle,
-                       IN THREADINFOCLASS ThreadInformationClass,
-                       IN PVOID ThreadInformation,
-                       IN ULONG ThreadInformationLength)
-{
-  PETHREAD Thread;
-  NTSTATUS Status;
-  union
-  {
-     KPRIORITY Priority;
-     LONG Increment;
-     KAFFINITY Affinity;
-     HANDLE Handle;
-     PVOID Address;
-  }u;
-  
-  PAGED_CODE();
-
-  if (ThreadInformationClass <= MaxThreadInfoClass &&
-      !SetInformationData[ThreadInformationClass].Implemented)
-    {
-      return STATUS_NOT_IMPLEMENTED;
-    }
-  if (ThreadInformationClass > MaxThreadInfoClass ||
-      SetInformationData[ThreadInformationClass].Size == 0)
-    {
-      return STATUS_INVALID_INFO_CLASS;
-    }
-  if (ThreadInformationLength != SetInformationData[ThreadInformationClass].Size)
-    {
-      return STATUS_INFO_LENGTH_MISMATCH;
-    }
-
-  Status = ObReferenceObjectByHandle (ThreadHandle,
-                                     THREAD_SET_INFORMATION,
-                                     PsThreadType,
-                                     ExGetPreviousMode (),
-                                     (PVOID*)&Thread,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-
-   Status = MmCopyFromCaller(&u.Priority,
-                            ThreadInformation,
-                            SetInformationData[ThreadInformationClass].Size);
-   if (NT_SUCCESS(Status))
-     {
-       switch (ThreadInformationClass)
-         {
-           case ThreadPriority:
-            if (u.Priority < LOW_PRIORITY || u.Priority >= MAXIMUM_PRIORITY)
-              {
-                Status = STATUS_INVALID_PARAMETER;
-                break;
-              }
-            KeSetPriorityThread(&Thread->Tcb, u.Priority);
-            break;
-       
-           case ThreadBasePriority:
-            KeSetBasePriorityThread (&Thread->Tcb, u.Increment);
-            break;
-       
-           case ThreadAffinityMask:
-            Status = KeSetAffinityThread(&Thread->Tcb, u.Affinity);
-            break;
-       
-           case ThreadImpersonationToken:
-            Status = PsAssignImpersonationToken (Thread, u.Handle);
-            break;
-               
-#ifdef _ENABLE_THRDEVTPAIR
-           case ThreadEventPair:
-            {
-              PKEVENT_PAIR EventPair;
-
-              Status = ObReferenceObjectByHandle(u.Handle,
-                                                 STANDARD_RIGHTS_ALL,
-                                                 ExEventPairObjectType,
-                                                 ExGetPreviousMode(),
-                                                 (PVOID*)&EventPair,
-                                                 NULL);
-              if (NT_SUCCESS(Status))
-                {
-                   ExpSwapThreadEventPair(Thread, EventPair); /* Note that the extra reference is kept intentionally */
-                }
-               break;
-            }
-#endif /* _ENABLE_THRDEVTPAIR */
-       
-           case ThreadQuerySetWin32StartAddress:
-            Thread->Win32StartAddress = u.Address;
-            break;
-
-           default:
-            /* Shoult never occure if the data table is correct */
-            KEBUGCHECK(0);
-        }
-     }
-  ObDereferenceObject (Thread);
-
-  return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtQueryInformationThread (IN   HANDLE          ThreadHandle,
-                         IN    THREADINFOCLASS ThreadInformationClass,
-                         OUT   PVOID           ThreadInformation,
-                         IN    ULONG           ThreadInformationLength,
-                         OUT   PULONG          ReturnLength  OPTIONAL)
-{
-   PETHREAD Thread;
-   NTSTATUS Status;
-   union
-   {
-      THREAD_BASIC_INFORMATION TBI;
-      KERNEL_USER_TIMES TTI;
-      PVOID Address;
-      LARGE_INTEGER Count;
-      BOOLEAN Last;
-   }u;
-   
-   PAGED_CODE();
-
-   if (ThreadInformationClass <= MaxThreadInfoClass &&
-       !QueryInformationData[ThreadInformationClass].Implemented)
-     {
-       return STATUS_NOT_IMPLEMENTED;
-     }
-   if (ThreadInformationClass > MaxThreadInfoClass ||
-       QueryInformationData[ThreadInformationClass].Size == 0)
-     {
-       return STATUS_INVALID_INFO_CLASS;
-     }
-   if (ThreadInformationLength != QueryInformationData[ThreadInformationClass].Size)
-     {
-       return STATUS_INFO_LENGTH_MISMATCH;
-     }
-
-   Status = ObReferenceObjectByHandle(ThreadHandle,
-                                     THREAD_QUERY_INFORMATION,
-                                     PsThreadType,
-                                     ExGetPreviousMode(),
-                                     (PVOID*)&Thread,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-
-   switch (ThreadInformationClass)
-     {
-       case ThreadBasicInformation:
-         /* A test on W2K agains ntdll shows NtQueryInformationThread return STATUS_PENDING
-          * as ExitStatus for current/running thread, while KETHREAD's ExitStatus is 
-          * 0. So do the conversion here:
-          * -Gunnar     */
-         u.TBI.ExitStatus = (Thread->ExitStatus == 0) ? STATUS_PENDING : Thread->ExitStatus;
-        u.TBI.TebBaseAddress = Thread->Tcb.Teb;
-        u.TBI.ClientId = Thread->Cid;
-        u.TBI.AffinityMask = Thread->Tcb.Affinity;
-        u.TBI.Priority = Thread->Tcb.Priority;
-        u.TBI.BasePriority = Thread->Tcb.BasePriority;
-        break;
-       
-       case ThreadTimes:
-        u.TTI.KernelTime.QuadPart = Thread->Tcb.KernelTime * 100000LL;
-         u.TTI.UserTime.QuadPart = Thread->Tcb.UserTime * 100000LL;
-         u.TTI.CreateTime = Thread->CreateTime;
-         /*This works*/
-        u.TTI.ExitTime = Thread->ExitTime;
-         break;
-
-       case ThreadQuerySetWin32StartAddress:
-         u.Address = Thread->Win32StartAddress;
-         break;
-
-       case ThreadPerformanceCount:
-         /* Nebbett says this class is always zero */
-         u.Count.QuadPart = 0;
-         break;
-
-       case ThreadAmILastThread:
-         if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
-            &Thread->ThreadsProcess->ThreadListHead)
-          {
-            u.Last = TRUE;
-          }
-         else
-          {
-            u.Last = FALSE;
-          }
-         break;
-       default:
-        /* Shoult never occure if the data table is correct */
-        KEBUGCHECK(0);
-     }
-   if (QueryInformationData[ThreadInformationClass].Size)
-     {
-       Status = MmCopyToCaller(ThreadInformation,
-                               &u.TBI,
-                              QueryInformationData[ThreadInformationClass].Size);
-     }
-   if (ReturnLength)
-     {
-       NTSTATUS Status2;
-       static ULONG Null = 0;
-       Status2 = MmCopyToCaller(ReturnLength,
-                               NT_SUCCESS(Status) ? &QueryInformationData[ThreadInformationClass].Size : &Null,
-                               sizeof(ULONG));
-       if (NT_SUCCESS(Status))
-         {
-          Status = Status2;
-        }
-     }
-
-   ObDereferenceObject(Thread);
-   return(Status);
-}
-
-
-VOID
-KeSetPreviousMode (ULONG Mode)
-{
-  PsGetCurrentThread()->Tcb.PreviousMode = (UCHAR)Mode;
-}
-
-
-/*
- * @implemented
- */
-KPROCESSOR_MODE STDCALL
-KeGetPreviousMode (VOID)
-{
-  return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
-}
-
-
-/*
- * @implemented
- */
-KPROCESSOR_MODE STDCALL
-ExGetPreviousMode (VOID)
-{
-  return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode;
-}
-
-/* EOF */