Author: ion
Date: Thu Jul 20 19:46:10 2006
New Revision: 23193
URL: 
http://svn.reactos.org/svn/reactos?rev=23193&view=rev
Log:
- Fix Win32K thread rundown bug, fixes shutdown crash and other bugchecks where some
ASSERT(Class->windows) wasn't 0.
- Close the right debug handle instead of some random value.
- Some generic formatting cleanup.
Modified:
    trunk/reactos/include/ndk/obfuncs.h
    trunk/reactos/ntoskrnl/KrnlFun.c
    trunk/reactos/ntoskrnl/ps/kill.c
Modified: trunk/reactos/include/ndk/obfuncs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/obfuncs.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/obfuncs.h (original)
+++ trunk/reactos/include/ndk/obfuncs.h Thu Jul 20 19:46:10 2006
@@ -29,6 +29,14 @@
 //
 // Object Functions
 //
+NTKERNELAPI
+NTSTATUS
+NTAPI
+ObCloseHandle(
+    IN HANDLE Handle,
+    IN KPROCESSOR_MODE AccessMode
+);
+
 NTKERNELAPI
 NTSTATUS
 NTAPI
Modified: trunk/reactos/ntoskrnl/KrnlFun.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=231…
==============================================================================
--- trunk/reactos/ntoskrnl/KrnlFun.c (original)
+++ trunk/reactos/ntoskrnl/KrnlFun.c Thu Jul 20 19:46:10 2006
@@ -25,16 +25,15 @@
 //  - Add tracing to iofunc.c
 //
 // Ps:
-//  - Use Process Rundown.
+//  - Use Process/Thread Rundown.
 //  - Use Process Pushlock Locks.
-//  - Use Safe Referencing in PsGetNextProcess/Thread.
+//  - Use Safe Referencing where needed.
 //  - Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
 //  - Use Security Locks in security.c
-//  - Fix referencing problem.
+//  - Figure out why processes don't die.
 //  - Generate process cookie for user-more thread.
 //  - Add security calls where necessary.
 //  - Add tracing.
-//  - Fix crash on shutdown due to possibly incorrect win32k uninitailization.
 //  - Add failure/race checks for thread creation.
 //
 // Ob:
Modified: trunk/reactos/ntoskrnl/ps/kill.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/kill.c?rev=231…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/kill.c (original)
+++ trunk/reactos/ntoskrnl/ps/kill.c Thu Jul 20 19:46:10 2006
@@ -14,11 +14,6 @@
 #define NDEBUG
 #include <internal/debug.h>
-#define LockEvent Spare0[0]
-#define LockCount Spare0[1]
-#define LockOwner Spare0[2]
-
-
 /* GLOBALS *******************************************************************/
 LIST_ENTRY PspReaperListHead = {0};
@@ -31,7 +26,7 @@
 extern PEPROCESS PsInitialSystemProcess;
 extern PEPROCESS PsIdleProcess;
-/* FUNCTIONS *****************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 NTSTATUS
 NTAPI
@@ -53,14 +48,16 @@
     InterlockedOr((PLONG)&Process->Flags, 8);
     /* Get the first thread */
-    while ((Thread = PsGetNextProcessThread(Process, Thread)))
+    Thread = PsGetNextProcessThread(Process, Thread);
+    while (Thread)
     {
         /* Kill it */
         PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
-        }
+        Thread = PsGetNextProcessThread(Process, Thread);
+    }
     /* Clear the handle table */
-    ObClearProcessHandleTable(Process);
+    if (Process->ObjectTable) ObClearProcessHandleTable(Process);
     /* Return success*/
     return STATUS_SUCCESS;
@@ -73,7 +70,8 @@
     PEPROCESS Process = NULL;
     /* Loop every process */
-    while ((Process == PsGetNextProcess(Process)))
+    Process == PsGetNextProcess(Process);
+    while (Process)
     {
         /* Make sure this isn't the idle or initial process */
         if ((Process != PsInitialSystemProcess) && (Process != PsIdleProcess))
@@ -81,6 +79,9 @@
             /* Kill it */
             PspTerminateProcess(Process, STATUS_SYSTEM_SHUTDOWN);
         }
+
+        /* Get the next process */
+        Process == PsGetNextProcess(Process);
     }
 }
@@ -140,17 +141,15 @@
 {
     PEPROCESS Process = (PEPROCESS)ObjectBody;
     KAPC_STATE ApcState;
-    DPRINT1("PspDeleteProcess(ObjectBody %x)\n", ObjectBody);
     PAGED_CODE();
-    DPRINT1("Name: %.16s\n", &Process->ImageFileName);
     /* Check if it has an Active Process Link */
     if (Process->ActiveProcessLinks.Flink)
     {
-    /* Remove it from the Active List */
-    ExAcquireFastMutex(&PspActiveProcessMutex);
-    RemoveEntryList(&Process->ActiveProcessLinks);
-    ExReleaseFastMutex(&PspActiveProcessMutex);
+        /* Remove it from the Active List */
+        ExAcquireFastMutex(&PspActiveProcessMutex);
+        RemoveEntryList(&Process->ActiveProcessLinks);
+        ExReleaseFastMutex(&PspActiveProcessMutex);
     }
     /* Check for Auditing information */
@@ -233,7 +232,7 @@
         /* Completely delete the Address Space */
         MmDeleteProcessAddressSpace(Process);
-}
+    }
     /* See if we have a PID */
     if(Process->UniqueProcessId)
@@ -272,9 +271,8 @@
 {
     PETHREAD Thread = (PETHREAD)ObjectBody;
     PEPROCESS Process = Thread->ThreadsProcess;
-    DPRINT1("PspDeleteThread(Thread %p, Process %p)\n", ObjectBody, Process);
     PAGED_CODE();
-    //ASSERT(Thread->Tcb.Win32Thread == NULL); FIXME
+    ASSERT(Thread->Tcb.Win32Thread == NULL);
     /* Check if we have a stack */
     if (Thread->Tcb.InitialStack)
@@ -284,9 +282,10 @@
                             Thread->Tcb.LargeStack);
     }
-    /* Delete the CID Handle */
-    if(Thread->Cid.UniqueThread)
-    {
+    /* Check if we have a CID Handle */
+    if (Thread->Cid.UniqueThread)
+    {
+        /* Delete the CID Handle */
         if (!(ExDestroyHandle(PspCidTable, Thread->Cid.UniqueThread)))
         {
             /* Something wrong happened, bugcheck */
@@ -338,7 +337,6 @@
     PKAPC Apc;
     PTOKEN PrimaryToken;
     PAGED_CODE();
-    DPRINT1("PspExitThread(%p, %lx)\n", PsGetCurrentThread(), ExitStatus);
     /* Get the Current Thread and Process */
     Thread = PsGetCurrentThread();
@@ -348,11 +346,12 @@
     /* Can't terminate a thread if it attached another process */
     if (KeIsAttachedProcess())
     {
+        /* Bugcheck */
         KEBUGCHECKEX(INVALID_PROCESS_ATTACH_ATTEMPT,
-                     (ULONG)CurrentProcess,
-                     (ULONG)Thread->Tcb.ApcState.Process,
-                     (ULONG)Thread->Tcb.ApcStateIndex,
-                     (ULONG)Thread);
+                     (ULONG_PTR)CurrentProcess,
+                     (ULONG_PTR)Thread->Tcb.ApcState.Process,
+                     (ULONG_PTR)Thread->Tcb.ApcStateIndex,
+                     (ULONG_PTR)Thread);
     }
     /* Lower to Passive Level */
@@ -361,8 +360,9 @@
     /* Can't be a worker thread */
     if (Thread->ActiveExWorker)
     {
+        /* Bugcheck */
         KEBUGCHECKEX(ACTIVE_EX_WORKER_THREAD_TERMINATION,
-                     (ULONG)Thread,
+                     (ULONG_PTR)Thread,
                      0,
                      0,
                      0);
@@ -371,6 +371,7 @@
     /* Can't have pending APCs */
     if (Thread->Tcb.CombinedApcDisable != 0)
     {
+        /* Bugcheck */
         KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT,
                      0,
                      Thread->Tcb.KernelApcDisable,
@@ -378,9 +379,8 @@
                      0);
     }
-    /* FIXME: Lock the thread
-     * ExAcquireRundownProtect(&Thread->RundownProtect);
-     */
+    /* Lock the thread */
+    ExWaitForRundownProtectionRelease(&Thread->RundownProtect);
     /* Cleanup the power state */
     PopCleanupPowerState((PPOWER_STATE)&Thread->Tcb.PowerState);
@@ -413,7 +413,8 @@
             if (CurrentProcess->ExitStatus == STATUS_PENDING)
             {
                 /* Use the last exit status */
-                CurrentProcess->ExitStatus = CurrentProcess->LastThreadExitStatus;
+                CurrentProcess->ExitStatus = CurrentProcess->
+                                             LastThreadExitStatus;
             }
         }
         else
@@ -427,15 +428,14 @@
     else if (ExitStatus != STATUS_THREAD_IS_TERMINATING)
     {
         /* Write down the exit status of the last thread to get killed */
-    CurrentProcess->LastThreadExitStatus = ExitStatus;
+        CurrentProcess->LastThreadExitStatus = ExitStatus;
     }
     /* Unlock the Process */
     PsUnlockProcess(CurrentProcess);
     /* Check if the process has a debug port and if this is a user thread */
-    if ((CurrentProcess->DebugPort) &&
-        !(Thread->SystemThread))
+    if ((CurrentProcess->DebugPort) && !(Thread->SystemThread))
     {
         /* Notify the Debug API. */
         Last ? DbgkExitProcess(CurrentProcess->ExitStatus) :
@@ -457,7 +457,7 @@
         {
             /* FIXME: Add critical process support */
             DbgBreakPoint();
-    }
+        }
         else
         {
             /* Bugcheck, we can't allow this */
@@ -560,7 +560,8 @@
     }
     /* Rundown Win32 Thread if there is one */
-    if (Thread->Tcb.Win32Thread) PspW32ThreadCallout(Thread, FALSE);
+    if (Thread->Tcb.Win32Thread) PspW32ThreadCallout(Thread,
+                                                     PsW32ThreadCalloutExit);
     /* If we are the last thread and have a W32 Process */
     if ((Last) && (CurrentProcess->Win32Process))
@@ -585,14 +586,12 @@
     /* FIXME: Rundown Registry Notifications (NtChangeNotify)
     CmNotifyRunDown(Thread); */
-    /* Clear NPX Thread */
-    (void)InterlockedCompareExchangePointer(&KeGetCurrentPrcb()->NpxThread, NULL,
Thread);
-
     /* Rundown Mutexes */
     KeRundownThread();
-    /* Free the TEB */
-    if((Teb = Thread->Tcb.Teb))
+    /* Check if we have a TEB */
+    Teb = Thread->Tcb.Teb;
+    if(Teb)
     {
         /* Check if the thread isn't terminated and if we should free stack */
         if (!(Thread->Terminated) && (Teb->FreeStackOnTermination))
@@ -607,10 +606,11 @@
                                 &Dummy,
                                 MEM_RELEASE);
         }
-
+
         /* Free the debug handle */
-        if (Teb->DbgSsReserved[2]) NtClose(Teb->DbgSsReserved[2]);
-
+        if (Teb->DbgSsReserved[1]) ObCloseHandle(Teb->DbgSsReserved[1],
+                                                 UserMode);
+
         /* Decommit the TEB */
         MmDeleteTeb(CurrentProcess, Teb);
         Thread->Tcb.Teb = NULL;
@@ -680,7 +680,7 @@
     /* Flush the User APCs */
     FirstEntry = KeFlushQueueApc(&Thread->Tcb, UserMode);
-    if (FirstEntry != NULL)
+    if (FirstEntry)
     {
         CurrentEntry = FirstEntry;
         do
@@ -713,7 +713,8 @@
     if (Thread->Tcb.LegoData) PspRunLegoRoutine(&Thread->Tcb);
     /* Flush the APC queue, which should be empty */
-    if ((FirstEntry = KeFlushQueueApc(&Thread->Tcb, KernelMode)))
+    FirstEntry = KeFlushQueueApc(&Thread->Tcb, KernelMode);
+    if (FirstEntry)
     {
         /* Bugcheck time */
         KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT,
@@ -740,10 +741,6 @@
 {
     NTSTATUS Status;
     PAGED_CODE();
-    DPRINT1("PsExitSpecialApc: [%p:%p], '%.16s')\n",
-            PsGetCurrentThread(),
-            PsGetCurrentProcess(),
-            PsGetCurrentProcess()->ImageFileName);
     /* Don't do anything unless we are in User-Mode */
     if (Apc->SystemArgument2)
@@ -766,16 +763,11 @@
     PKAPC Apc = (PKAPC)SystemArgument1;
     PETHREAD Thread = PsGetCurrentThread();
     PAGED_CODE();
-    DPRINT1("PspExitNormalApc: [%p:%p], '%.16s')\n",
-            PsGetCurrentThread(),
-            PsGetCurrentProcess(),
-            PsGetCurrentProcess()->ImageFileName);
     /* This should never happen */
     ASSERT(!(((ULONG_PTR)SystemArgument2) & 1));
     /* If we're here, this is not a System Thread, so kill it from User-Mode */
-    DPRINT1("Initializing User-Mode APC\n");
     KeInitializeApc(Apc,
                     &Thread->Tcb,
                     OriginalApcEnvironment,
@@ -812,7 +804,6 @@
     NTSTATUS Status = STATUS_SUCCESS;
     ULONG Flags;
     PAGED_CODE();
-    DPRINT1("PspTerminateThreadByPointer(%p, %lx)\n", Thread, ExitStatus);
     /* Check if this is a Critical Thread, and Bugcheck */
     if (Thread->BreakOnTermination)
@@ -823,7 +814,7 @@
     }
     /* Check if we are already inside the thread */
-    if (bSelf || (PsGetCurrentThread() == Thread))
+    if ((bSelf) || (PsGetCurrentThread() == Thread))
     {
         /* This should only happen at passive */
         ASSERT_IRQL(PASSIVE_LEVEL);
@@ -836,11 +827,7 @@
     }
     /* This shouldn't be a system thread */
-    if (Thread->SystemThread)
-    {
-        DPRINT1("A system thread is being illegaly terminated\n");
-        return STATUS_ACCESS_DENIED;
-    }
+    if (Thread->SystemThread) return STATUS_ACCESS_DENIED;
     /* Allocate the APC */
     Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
@@ -880,7 +867,6 @@
     ExFreePool(Apc);
     /* Return Status */
-    DPRINT1("Fail return: %lx\n", Status);
     return Status;
 }
@@ -891,7 +877,6 @@
 {
     ULONG Actual;
     PAGED_CODE();
-    DPRINT1("PspExitProcess %p\n", Process);
     /* Set Process Delete flag */
     InterlockedOr((PLONG)&Process->Flags, 4);
@@ -931,10 +916,8 @@
             /* Set it to default */
             ZwSetTimerResolution(KeMaximumIncrement, 0, &Actual);
         }
-
-        /*
-         * Check if we are part of a Job, and if the job has a completion port
-         */
+
+        /* Check if we are part of a Job that has a completion port */
         if ((Process->Job) && (Process->Job->CompletionPort))
         {
             /* FIXME: Check job status code and do I/O completion if needed */
@@ -949,9 +932,34 @@
     }
 }
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
-NtTerminateProcess(IN HANDLE ProcessHandle  OPTIONAL,
+PsTerminateSystemThread(NTSTATUS ExitStatus)
+{
+    PETHREAD Thread = PsGetCurrentThread();
+
+    /* Make sure this is a system thread */
+    if (Thread->SystemThread)
+    {
+        DPRINT1("Trying to Terminate a non-system thread!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Terminate it for real */
+    return PspTerminateThreadByPointer(Thread, ExitStatus, TRUE);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
                    IN NTSTATUS ExitStatus)
 {
     NTSTATUS Status;
@@ -959,8 +967,6 @@
     PETHREAD Thread, CurrentThread = PsGetCurrentThread();
     BOOLEAN KillByHandle;
     PAGED_CODE();
-    DPRINT1("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
-            ProcessHandle, ExitStatus);
     /* Remember how we will kill it */
     KillByHandle = (ProcessHandle != NULL);
@@ -973,11 +979,7 @@
                                        KeGetPreviousMode(),
                                        (PVOID*)&Process,
                                        NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Invalid handle to Process\n");
-        return(Status);
-    }
+    if (!NT_SUCCESS(Status)) return(Status);
     /* Check if this is a Critical Process, and Bugcheck */
     if (Process->BreakOnTermination)
@@ -988,14 +990,15 @@
     }
     /* Lock the Process */
-    PsLockProcess(Process, FALSE);
+    ExAcquireRundownProtection(&Process->RundownProtect);
     /* Set the exit flag */
     if (!KillByHandle) InterlockedOr((PLONG)&Process->Flags, 8);
     /* Get the first thread */
     Status = STATUS_NOTHING_TO_TERMINATE;
-    if ((Thread = PsGetNextProcessThread(Process, NULL)))
+    Thread = PsGetNextProcessThread(Process, NULL);
+    if (Thread)
     {
         /* We know we have at least a thread */
         Status = STATUS_SUCCESS;
@@ -1015,7 +1018,7 @@
     }
     /* Unlock the process */
-    PsUnlockProcess(Process);
+    ExReleaseRundownProtection(&Process->RundownProtect);
     /* Check if we are killing ourselves */
     if (Process != CurrentProcess)
@@ -1038,10 +1041,9 @@
     /* Check if there was nothing to terminate, or if we have a Debug Port */
     if ((Status == STATUS_NOTHING_TO_TERMINATE) ||
-        (Process->DebugPort && KillByHandle))
+        ((Process->DebugPort) && (KillByHandle)))
     {
         /* Clear the handle table */
-        DPRINT1("Clearing OB Table\n");
         ObClearProcessHandleTable(Process);
         /* Return status now */
@@ -1052,7 +1054,6 @@
     ObDereferenceObject(Process);
     /* Return status */
-    DPRINT1("Returning: %lx\n", Status);
     return Status;
 }
@@ -1065,8 +1066,7 @@
     PETHREAD CurrentThread = PsGetCurrentThread();
     NTSTATUS Status;
     PAGED_CODE();
-    DPRINT1("NtTerminateThread: %lx %lx\n", ThreadHandle, ExitStatus);
-
+
     /* Handle the special NULL case */
     if (!ThreadHandle)
     {
@@ -1074,14 +1074,11 @@
         if (PsGetCurrentProcess()->ActiveThreads == 1)
         {
             /* This is invalid */
-            DPRINT1("Can't terminate self\n");
             return STATUS_CANT_TERMINATE_SELF;
         }
-        else
-        {
-            /* Terminate us directly */
-            goto TerminateSelf;
-        }
+
+        /* Terminate us directly */
+        goto TerminateSelf;
     }
     else if (ThreadHandle == NtCurrentThread())
     {
@@ -1099,16 +1096,12 @@
                                        KeGetPreviousMode(),
                                        (PVOID*)&Thread,
                                        NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Could not reference thread object\n");
-        return Status;
-    }
+    if (!NT_SUCCESS(Status)) return Status;
     /* Check to see if we're running in the same thread */
     if (Thread != CurrentThread)
     {
-             /* Terminate it */
+        /* Terminate it */
         Status = PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
         /* Dereference the Thread and return */
@@ -1121,32 +1114,13 @@
         goto TerminateSelf;
     }
+    /* Return status */
     return Status;
 }
-/*
- * @implemented
- */
 NTSTATUS
 NTAPI
-PsTerminateSystemThread(NTSTATUS ExitStatus)
-{
-    PETHREAD Thread = PsGetCurrentThread();
-
-    /* Make sure this is a system thread */
-    if (Thread->SystemThread)
-    {
-        DPRINT1("Trying to Terminate a non-system thread!\n");
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Terminate it for real */
-    return PspTerminateThreadByPointer(Thread, ExitStatus, TRUE);
-}
-
-NTSTATUS
-NTAPI
-NtRegisterThreadTerminatePort(HANDLE PortHandle)
+NtRegisterThreadTerminatePort(IN HANDLE PortHandle)
 {
     NTSTATUS Status;
     PTERMINATION_PORT TerminationPort;
@@ -1161,17 +1135,14 @@
                                        KeGetPreviousMode(),
                                        &TerminationLpcPort,
                                        NULL);
-    if (!NT_SUCCESS(Status)) {
-
-        DPRINT1("Failed to reference Port\n");
-        return(Status);
-    }
+    if (!NT_SUCCESS(Status)) return(Status);
     /* Allocate the Port and make sure it suceeded */
-    if((TerminationPort = ExAllocatePoolWithTag(NonPagedPool,
-                                                sizeof(TERMINATION_PORT),
-                                                TAG('P', 's',
'T', '=')))) {
-
+    TerminationPort = ExAllocatePoolWithTag(NonPagedPool,
+                                            sizeof(TERMINATION_PORT),
+                                            TAG('P', 's', 'T',
'='));
+    if(TerminationPort)
+    {
         /* Associate the Port */
         Thread = PsGetCurrentThread();
         TerminationPort->Port = TerminationLpcPort;
@@ -1179,12 +1150,10 @@
         Thread->TerminationPort = TerminationPort;
         /* Return success */
-        return(STATUS_SUCCESS);
-
-    } else {
-
-        /* Dereference and Fail */
-        ObDereferenceObject(TerminationPort);
-        return(STATUS_INSUFFICIENT_RESOURCES);
-    }
-}
+        return STATUS_SUCCESS;
+    }
+
+    /* Dereference and Fail */
+    ObDereferenceObject(TerminationPort);
+    return STATUS_INSUFFICIENT_RESOURCES;
+}