- Use _SEH2_YIELD when returning from an exception instead of returning outside the...
[reactos.git] / reactos / ntoskrnl / dbgk / dbgkobj.c
index b3d5d6d..6b509a0 100644 (file)
@@ -53,17 +53,17 @@ DbgkpQueueMessage(IN PEPROCESS Process,
               Process, Thread, Message, Flags);
 
     /* Check if we have to allocate a debug event */
-    NewEvent = (Flags & 2) ? TRUE : FALSE;
+    NewEvent = (Flags & DEBUG_EVENT_NOWAIT) ? TRUE : FALSE;
     if (NewEvent)
     {
         /* Allocate it */
         DebugEvent = ExAllocatePoolWithTag(NonPagedPool,
                                            sizeof(DEBUG_EVENT),
-                                           TAG('D', 'b', 'g', 'E'));
+                                           'EgbD');
         if (!DebugEvent) return STATUS_INSUFFICIENT_RESOURCES;
 
         /* Set flags */
-        DebugEvent->Flags = Flags | 4;
+        DebugEvent->Flags = Flags | DEBUG_EVENT_INACTIVE;
 
         /* Reference the thread and process */
         ObReferenceObject(Thread);
@@ -209,16 +209,17 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message,
 {
     NTSTATUS Status;
     UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH];
+    BOOLEAN Suspended = FALSE;
     PAGED_CODE();
 
     /* Suspend process if required */
-    if (SuspendProcess) DbgkpSuspendProcess();
+    if (SuspendProcess) Suspended = DbgkpSuspendProcess();
 
     /* Set return status */
     Message->ReturnedStatus = STATUS_PENDING;
 
     /* Set create process reported state */
-    PsGetCurrentProcess()->CreateReported = TRUE;
+    PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
 
     /* Send the LPC command */
     Status = LpcRequestWaitReplyPort(Port,
@@ -232,27 +233,28 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message,
     if (NT_SUCCESS(Status)) RtlCopyMemory(Message, Buffer, sizeof(DBGKM_MSG));
 
     /* Resume the process if it was suspended */
-    if (SuspendProcess) DbgkpResumeProcess();
+    if (Suspended) DbgkpResumeProcess();
     return Status;
 }
 
 NTSTATUS
 NTAPI
 DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg,
-                    IN ULONG Flags)
+                    IN BOOLEAN SuspendProcess)
 {
     NTSTATUS Status;
+    BOOLEAN Suspended = FALSE;
     PAGED_CODE();
-    DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p Flags: %lx\n", ApiMsg, Flags);
+    DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p SuspendProcess: %lx\n", ApiMsg, SuspendProcess);
 
     /* Suspend process if required */
-    if (Flags) DbgkpSuspendProcess();
+    if (SuspendProcess) Suspended = DbgkpSuspendProcess();
 
     /* Set return status */
     ApiMsg->ReturnedStatus = STATUS_PENDING;
 
     /* Set create process reported state */
-    PsGetCurrentProcess()->CreateReported = TRUE;
+    PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
 
     /* Send the LPC command */
     Status = DbgkpQueueMessage(PsGetCurrentProcess(),
@@ -265,7 +267,7 @@ DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg,
     ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
 
     /* Resume the process if it was suspended */
-    if (Flags) DbgkpResumeProcess();
+    if (Suspended) DbgkpResumeProcess();
     return Status;
 }
 
@@ -426,17 +428,17 @@ DbgkpWakeTarget(IN PDEBUG_EVENT DebugEvent)
     DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent);
 
     /* Check if we have to wake the thread */
-    if (DebugEvent->Flags & 20) PsResumeThread(Thread, NULL);
+    if (DebugEvent->Flags & DEBUG_EVENT_SUSPEND) PsResumeThread(Thread, NULL);
 
     /* Check if we had locked the thread */
-    if (DebugEvent->Flags & 8)
+    if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
     {
         /* Unlock it */
         ExReleaseRundownProtection(&Thread->RundownProtect);
     }
 
     /* Check if we have to wake up the event */
-    if (DebugEvent->Flags & 2)
+    if (DebugEvent->Flags & DEBUG_EVENT_NOWAIT)
     {
         /* Otherwise, free the debug event */
         DbgkpFreeDebugEvent(DebugEvent);
@@ -550,7 +552,7 @@ DbgkpPostFakeModuleMessages(IN PEPROCESS Process,
         Status = DbgkpQueueMessage(Process,
                                    Thread,
                                    &ApiMessage,
-                                   2,
+                                   DEBUG_EVENT_NOWAIT,
                                    DebugObject);
         if (!NT_SUCCESS(Status))
         {
@@ -603,7 +605,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
     else
     {
         /* Get the first thread ourselves */
-        ThisThread = PsGetNextProcessThread(Process, OldThread);
+        ThisThread = PsGetNextProcessThread(Process, NULL);
         IsFirstThread = TRUE;
     }
 
@@ -619,7 +621,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
         if (ExAcquireRundownProtection(&ThisThread->RundownProtect))
         {
             /* Acquire worked, set flags */
-            Flags = 0x8 | 0x2;
+            Flags = DEBUG_EVENT_RELEASE | DEBUG_EVENT_NOWAIT;
 
             /* Check if this is a user thread */
             if (!ThisThread->SystemThread)
@@ -628,14 +630,14 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
                 if (NT_SUCCESS(PsSuspendThread(ThisThread, NULL)))
                 {
                     /* Remember this */
-                    Flags = 0x8 | 0x2 | 0x20;
+                    Flags |= DEBUG_EVENT_SUSPEND;
                 }
             }
         }
         else
         {
             /* Couldn't acquire rundown */
-            Flags = 0x10 | 0x2;
+            Flags = DEBUG_EVENT_PROTECT_FAILED | DEBUG_EVENT_NOWAIT;
         }
 
         /* Clear the API Message */
@@ -643,7 +645,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
 
         /* Check if this is the first thread */
         if ((IsFirstThread) &&
-            !(Flags & 0x10) &&
+            !(Flags & DEBUG_EVENT_PROTECT_FAILED) &&
             !(ThisThread->SystemThread) &&
             (ThisThread->GrantedAccess))
         {
@@ -710,9 +712,27 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
                                    DebugObject);
         if (!NT_SUCCESS(Status))
         {
-            /* We failed. FIXME: Handle this */
-            DPRINT1("Unhandled Dbgk codepath!\n");
-            ASSERT(FALSE);
+            /* Resume the thread if it was suspended */
+            if (Flags & DEBUG_EVENT_SUSPEND) PsResumeThread(ThisThread, NULL);
+
+            /* Check if we acquired rundown */
+            if (Flags & DEBUG_EVENT_RELEASE)
+            {
+                /* Release it */
+                ExReleaseRundownProtection(&ThisThread->RundownProtect);
+            }
+
+            /* If this was a process create, check if we got a handle */
+            if ((ApiMessage.ApiNumber == DbgKmCreateProcessApi) &&
+                 (CreateProcess->FileHandle))
+            {
+                /* Close it */
+                ObCloseHandle(CreateProcess->FileHandle, KernelMode);
+            }
+
+            /* Release our reference and break out */
+            ObDereferenceObject(ThisThread);
+            break;
         }
 
         /* Check if this was the first message */
@@ -722,7 +742,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
             IsFirstThread = FALSE;
 
             /* Reference this thread and set it as first */
-            ObDereferenceObject(ThisThread);
+            ObReferenceObject(ThisThread);
             pFirstThread = ThisThread;
         }
 
@@ -734,9 +754,10 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
     /* Check the API status */
     if (!NT_SUCCESS(Status))
     {
-        /* We failed. FIXME: Handle this */
-        DPRINT1("Unhandled Dbgk codepath!\n");
-        ASSERT(FALSE);
+        /* Dereference and fail */
+        if (pFirstThread) ObDereferenceObject(pFirstThread);
+        if (pLastThread) ObDereferenceObject(pLastThread);
+        return Status;
     }
 
     /* Make sure we have a first thread */
@@ -844,13 +865,13 @@ DbgkpConvertKernelToUserStateChange(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange,
         case DbgKmExceptionApi:
 
             /* Look at the exception code */
-            if (DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
+            if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
                 STATUS_BREAKPOINT)
             {
                 /* Update this as a breakpoint exception */
                 WaitStateChange->NewState = DbgBreakpointStateChange;
             }
-            else if (DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
+            else if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
                      STATUS_SINGLE_STEP)
             {
                 /* Update this as a single step exception */
@@ -1079,6 +1100,7 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL,
     BOOLEAN DebugPortCleared = FALSE;
     PLIST_ENTRY DebugEventList;
     PDEBUG_EVENT DebugEvent;
+    PAGED_CODE();
     DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n",
               OwnerProcess, DebugObject);
 
@@ -1258,11 +1280,12 @@ ThreadScan:
         else
         {
             /* Set the process flags */
-            InterlockedOr((PLONG)&Process->Flags,
-                          PSF_NO_DEBUG_INHERIT_BIT | PSF_CREATE_REPORTED_BIT);
+            PspSetProcessFlag(Process,
+                              PSF_NO_DEBUG_INHERIT_BIT |
+                              PSF_CREATE_REPORTED_BIT);
 
             /* Reference the debug object */
-            ObDereferenceObject(DebugObject);
+            ObReferenceObject(DebugObject);
         }
     }
 
@@ -1270,14 +1293,15 @@ ThreadScan:
     NextEntry = DebugObject->EventList.Flink;
     while (NextEntry != &DebugObject->EventList)
     {
-        /* Get the debug event */
+        /* Get the debug event and go to the next entry */
         DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+        NextEntry = NextEntry->Flink;
         DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx TH: %p/%p\n",
                   DebugEvent, DebugEvent->Flags,
                   DebugEvent->BackoutThread, PsGetCurrentThread());
 
         /* Check for if the debug event queue needs flushing */
-        if ((DebugEvent->Flags & 4) &&
+        if ((DebugEvent->Flags & DEBUG_EVENT_INACTIVE) &&
             (DebugEvent->BackoutThread == PsGetCurrentThread()))
         {
             /* Get the event's thread */
@@ -1291,7 +1315,7 @@ ThreadScan:
                 (!EventThread->SystemThread))
             {
                 /* Check if we couldn't acquire rundown for it */
-                if (DebugEvent->Flags & 0x10)
+                if (DebugEvent->Flags & DEBUG_EVENT_PROTECT_FAILED)
                 {
                     /* Set the skip termination flag */
                     PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
@@ -1306,7 +1330,7 @@ ThreadScan:
                     if (DoSetEvent)
                     {
                         /* Do it */
-                        DebugEvent->Flags &= ~4;
+                        DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
                         KeSetEvent(&DebugObject->EventsPresent,
                                    IO_NO_INCREMENT,
                                    FALSE);
@@ -1328,16 +1352,13 @@ ThreadScan:
             }
 
             /* Check if the lock is held */
-            if (DebugEvent->Flags & 8)
+            if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
             {
                 /* Release it */
-                DebugEvent->Flags &= ~8;
+                DebugEvent->Flags &= ~DEBUG_EVENT_RELEASE;
                 ExReleaseRundownProtection(&EventThread->RundownProtect);
             }
         }
-
-        /* Go to the next entry */
-        NextEntry = NextEntry->Flink;
     }
 
     /* Release the debug object */
@@ -1354,7 +1375,7 @@ ThreadScan:
     {
         /* Remove the event */
         NextEntry = RemoveHeadList(&TempList);
-        DebugEvent = CONTAINING_RECORD (NextEntry, DEBUG_EVENT, EventList);
+        DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
 
         /* Wake it */
         DbgkpWakeTarget(DebugEvent);
@@ -1368,12 +1389,88 @@ ThreadScan:
 NTSTATUS
 NTAPI
 DbgkClearProcessDebugObject(IN PEPROCESS Process,
-                            IN PDEBUG_OBJECT SourceDebugObject)
+                            IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
 {
-    /* FIXME: TODO */
-    DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n",
+    PDEBUG_OBJECT DebugObject;
+    PDEBUG_EVENT DebugEvent;
+    LIST_ENTRY TempList;
+    PLIST_ENTRY NextEntry;
+    PAGED_CODE();
+    DBGKTRACE(DBGK_OBJECT_DEBUG, "Process: %p DebugObject: %p\n",
               Process, SourceDebugObject);
-    return STATUS_UNSUCCESSFUL;
+
+    /* Acquire the port lock */
+    ExAcquireFastMutex(&DbgkpProcessDebugPortMutex);
+
+    /* Get the Process Debug Object */
+    DebugObject = Process->DebugPort;
+
+    /* 
+     * Check if the process had an object and it matches,
+     * or if the process had an object but none was specified
+     * (in which we are called from NtTerminateProcess)
+     */
+    if ((DebugObject) &&
+        ((DebugObject == SourceDebugObject) ||
+         (SourceDebugObject == NULL)))
+    {
+        /* Clear the debug port */
+        Process->DebugPort = NULL;
+
+        /* Release the port lock and remove the PEB flag */
+        ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
+        DbgkpMarkProcessPeb(Process);
+    }
+    else
+    {
+        /* Release the port lock and fail */
+        ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
+        return STATUS_PORT_NOT_SET;
+    }
+
+    /* Initialize the temporary list */
+    InitializeListHead(&TempList);
+
+    /* Acquire the Object */
+    ExAcquireFastMutex(&DebugObject->Mutex);
+
+    /* Loop the events */
+    NextEntry = DebugObject->EventList.Flink;
+    while (NextEntry != &DebugObject->EventList)
+    {
+        /* Get the Event and go to the next entry */
+        DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+        NextEntry = NextEntry->Flink;
+
+        /* Check that it belongs to the specified process */
+        if (DebugEvent->Process == Process)
+        {
+            /* Insert it into the temporary list */
+            RemoveEntryList(&DebugEvent->EventList);
+            InsertTailList(&TempList, &DebugEvent->EventList);
+        }
+    }
+
+    /* Release the Object */
+    ExReleaseFastMutex(&DebugObject->Mutex);
+
+    /* Release the initial reference */
+    ObDereferenceObject(DebugObject);
+
+    /* Loop our temporary list */
+    while (!IsListEmpty(&TempList))
+    {
+        /* Remove the event */
+        NextEntry = RemoveHeadList(&TempList);
+        DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+
+        /* Wake it up */
+        DebugEvent->Status = STATUS_DEBUGGER_INACTIVE;
+        DbgkpWakeTarget(DebugEvent);
+    }
+
+    /* Return Success */
+    return STATUS_SUCCESS;
 }
 
 VOID
@@ -1407,36 +1504,41 @@ DbgkInitialize(VOID)
 
 /* PUBLIC FUNCTIONS **********************************************************/
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtCreateDebugObject(OUT PHANDLE DebugHandle,
                     IN ACCESS_MASK DesiredAccess,
                     IN POBJECT_ATTRIBUTES ObjectAttributes,
-                    IN BOOLEAN KillProcessOnExit)
+                    IN ULONG Flags)
 {
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     PDEBUG_OBJECT DebugObject;
     HANDLE hDebug;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     PAGED_CODE();
 
     /* Check if we were called from user mode*/
     if (PreviousMode != KernelMode)
     {
         /* Enter SEH for probing */
-        _SEH_TRY
+        _SEH2_TRY
         {
             /* Probe the handle */
             ProbeForWriteHandle(DebugHandle);
         }
-        _SEH_HANDLE
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            /* Get exception error */
-            Status = _SEH_GetExceptionCode();
-        } _SEH_END;
-        if (!NT_SUCCESS(Status)) return Status;
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        } _SEH2_END;
     }
 
+    /* Check for invalid flags */
+    if (Flags & ~DBGK_ALL_FLAGS) return STATUS_INVALID_PARAMETER;
+
     /* Create the Object */
     Status = ObCreateObject(PreviousMode,
                             DbgkDebugObjectType,
@@ -1461,7 +1563,11 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle,
                           FALSE);
 
         /* Set the Flags */
-        DebugObject->KillProcessOnExit = KillProcessOnExit;
+        DebugObject->Flags = 0;
+        if (Flags & DBGK_KILL_PROCESS_ON_EXIT)
+        {
+            DebugObject->KillProcessOnExit = TRUE;
+        }
 
         /* Insert it */
         Status = ObInsertObject((PVOID)DebugObject,
@@ -1472,14 +1578,17 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle,
                                  &hDebug);
         if (NT_SUCCESS(Status))
         {
-            _SEH_TRY
+            /* Enter SEH to protect the write */
+            _SEH2_TRY
             {
+                /* Return the handle */
                 *DebugHandle = hDebug;
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(ExSystemExceptionFilter())
             {
-                Status = _SEH_GetExceptionCode();
-            } _SEH_END;
+                /* Get the exception code */
+                Status = _SEH2_GetExceptionCode();
+            } _SEH2_END;
         }
     }
 
@@ -1489,6 +1598,9 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle,
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtDebugContinue(IN HANDLE DebugHandle,
@@ -1497,7 +1609,7 @@ NtDebugContinue(IN HANDLE DebugHandle,
 {
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     PDEBUG_OBJECT DebugObject;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     PDEBUG_EVENT DebugEvent = NULL, DebugEventToWake = NULL;
     PLIST_ENTRY ListHead, NextEntry;
     BOOLEAN NeedsWake = FALSE;
@@ -1510,19 +1622,18 @@ NtDebugContinue(IN HANDLE DebugHandle,
     if (PreviousMode != KernelMode)
     {
         /* Enter SEH for probing */
-        _SEH_TRY
+        _SEH2_TRY
         {
             /* Probe the handle */
             ProbeForRead(AppClientId, sizeof(CLIENT_ID), sizeof(ULONG));
             ClientId = *AppClientId;
             AppClientId = &ClientId;
         }
-        _SEH_HANDLE
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            /* Get exception error */
-            Status = _SEH_GetExceptionCode();
-        } _SEH_END;
-        if (!NT_SUCCESS(Status)) return Status;
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        } _SEH2_END;
     }
 
     /* Make sure that the status is valid */
@@ -1567,8 +1678,8 @@ NtDebugContinue(IN HANDLE DebugHandle,
                     if (NeedsWake)
                     {
                         /* Wake it up and break out */
-                        DebugEvent->Flags &= ~4;
-                        KeSetEvent(&DebugEvent->ContinueEvent,
+                        DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
+                        KeSetEvent(&DebugObject->EventsPresent,
                                    IO_NO_INCREMENT,
                                    FALSE);
                         break;
@@ -1576,7 +1687,7 @@ NtDebugContinue(IN HANDLE DebugHandle,
 
                     /* Compare thread ID and flag */
                     if ((DebugEvent->ClientId.UniqueThread ==
-                        AppClientId->UniqueThread) && (DebugEvent->Flags & 1))
+                        AppClientId->UniqueThread) && (DebugEvent->Flags & DEBUG_EVENT_READ))
                     {
                         /* Remove the event from the list */
                         RemoveEntryList(NextEntry);
@@ -1601,11 +1712,11 @@ NtDebugContinue(IN HANDLE DebugHandle,
             if (NeedsWake)
             {
                 /* Set the continue status */
-                DebugEvent->ApiMsg.ReturnedStatus = ContinueStatus;
-                DebugEvent->Status = STATUS_SUCCESS;
+                DebugEventToWake->ApiMsg.ReturnedStatus = ContinueStatus;
+                DebugEventToWake->Status = STATUS_SUCCESS;
 
                 /* Wake the target */
-                DbgkpWakeTarget(DebugEvent);
+                DbgkpWakeTarget(DebugEventToWake);
             }
             else
             {
@@ -1619,6 +1730,9 @@ NtDebugContinue(IN HANDLE DebugHandle,
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtDebugActiveProcess(IN HANDLE ProcessHandle,
@@ -1626,7 +1740,7 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle,
 {
     PEPROCESS Process;
     PDEBUG_OBJECT DebugObject;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     PETHREAD LastThread;
     NTSTATUS Status;
     PAGED_CODE();
@@ -1642,8 +1756,9 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle,
                                        NULL);
     if (!NT_SUCCESS(Status)) return Status;
 
-    /* Don't allow debugging the initial system process */
-    if (Process == PsInitialSystemProcess)
+    /* Don't allow debugging the current process or the system process */
+    if ((Process == PsGetCurrentProcess()) ||
+         (Process == PsInitialSystemProcess))
     {
         /* Dereference and fail */
         ObDereferenceObject(Process);
@@ -1691,6 +1806,9 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle,
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtRemoveProcessDebug(IN HANDLE ProcessHandle,
@@ -1698,7 +1816,7 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle,
 {
     PEPROCESS Process;
     PDEBUG_OBJECT DebugObject;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status;
     PAGED_CODE();
     DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
@@ -1736,6 +1854,9 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle,
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtSetInformationDebugObject(IN HANDLE DebugHandle,
@@ -1746,7 +1867,7 @@ NtSetInformationDebugObject(IN HANDLE DebugHandle,
 {
     PDEBUG_OBJECT DebugObject;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION DebugInfo = DebugInformation;
     PAGED_CODE();
 
@@ -1758,25 +1879,25 @@ NtSetInformationDebugObject(IN HANDLE DebugHandle,
                                        DebugInformation,
                                        DebugInformationLength,
                                        PreviousMode);
+    if (!NT_SUCCESS(Status)) return Status;
 
     /* Check if the caller wanted the return length */
     if (ReturnLength)
     {
         /* Enter SEH for probe */
-        _SEH_TRY
+        _SEH2_TRY
         {
             /* Return required length to user-mode */
             ProbeForWriteUlong(ReturnLength);
             *ReturnLength = sizeof(*DebugInfo);
         }
-        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        _SEH2_EXCEPT(ExSystemExceptionFilter())
         {
-            /* Get SEH Exception code */
-            Status = _SEH_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
-        _SEH_END;
+        _SEH2_END;
     }
-    if (!NT_SUCCESS(Status)) return Status;
 
     /* Open the Object */
     Status = ObReferenceObjectByHandle(DebugHandle,
@@ -1813,6 +1934,9 @@ NtSetInformationDebugObject(IN HANDLE DebugHandle,
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 NTAPI
 NtWaitForDebugEvent(IN HANDLE DebugHandle,
@@ -1821,7 +1945,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                     OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
 {
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    LARGE_INTEGER SafeTimeOut;
+    LARGE_INTEGER LocalTimeOut;
     PEPROCESS Process;
     LARGE_INTEGER StartTime;
     PETHREAD Thread;
@@ -1829,50 +1953,51 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
     LARGE_INTEGER NewTime;
     PDEBUG_OBJECT DebugObject;
     DBGUI_WAIT_STATE_CHANGE WaitStateChange;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     PDEBUG_EVENT DebugEvent = NULL, DebugEvent2;
     PLIST_ENTRY ListHead, NextEntry, NextEntry2;
     PAGED_CODE();
     DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
 
-    /* Clear the initial wait state change structure */
+    /* Clear the initial wait state change structure and the timeout */
     RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
+    LocalTimeOut.QuadPart = 0;
 
-    /* Protect probe in SEH */
-    _SEH_TRY
+    /* Check if we were called from user mode */
+    if (PreviousMode != KernelMode)
     {
-        /* Check if we came with a timeout */
-        if (Timeout)
+        /* Protect probe in SEH */
+        _SEH2_TRY
         {
-            /* Check if the call was from user mode */
-            if (PreviousMode != KernelMode)
+            /* Check if we came with a timeout */
+            if (Timeout)
             {
                 /* Probe it */
                 ProbeForReadLargeInteger(Timeout);
-            }
 
-            /* Make a local copy */
-            SafeTimeOut = *Timeout;
-            Timeout = &SafeTimeOut;
-
-            /* Query the current time */
-            KeQuerySystemTime(&StartTime);
-        }
+                /* Make a local copy */
+                LocalTimeOut = *Timeout;
+                Timeout = &LocalTimeOut;
+            }
 
-        /* Check if the call was from user mode */
-        if (PreviousMode != KernelMode)
-        {
             /* Probe the state change structure */
             ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
         }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
     }
-    _SEH_HANDLE
+    else
     {
-        /* Get the exception code */
-        Status = _SEH_GetExceptionCode();
+        /* Copy directly */
+        if (Timeout) LocalTimeOut = *Timeout;
     }
-    _SEH_END;
-    if (!NT_SUCCESS(Status)) return Status;
+
+    /* If we were passed a timeout, query the current time */
+    if (Timeout) KeQuerySystemTime(&StartTime);
 
     /* Get the debug object */
     Status = ObReferenceObjectByHandle(DebugHandle,
@@ -1890,7 +2015,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
     /* Wait on the debug object given to us */
     while (TRUE)
     {
-        Status = KeWaitForSingleObject(DebugObject,
+        Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
                                        Executive,
                                        PreviousMode,
                                        Alertable,
@@ -1929,7 +2054,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                           DebugEvent, DebugEvent->Flags);
 
                 /* Check flags */
-                if (!(DebugEvent->Flags & (4 | 1)))
+                if (!(DebugEvent->Flags & (DEBUG_EVENT_INACTIVE | DEBUG_EVENT_READ)))
                 {
                     /* We got an event */
                     GotEvent = TRUE;
@@ -1948,7 +2073,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                             DebugEvent->ClientId.UniqueProcess)
                         {
                             /* Found it, break out */
-                            DebugEvent->Flags |= 4;
+                            DebugEvent->Flags |= DEBUG_EVENT_INACTIVE;
                             DebugEvent->BackoutThread = NULL;
                             GotEvent = FALSE;
                             break;
@@ -1980,7 +2105,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
                                                     DebugEvent);
 
                 /* Set flag */
-                DebugEvent->Flags |= 1;
+                DebugEvent->Flags |= DEBUG_EVENT_READ;
             }
             else
             {
@@ -2000,17 +2125,17 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
         if (!GotEvent)
         {
             /* Check if we can wait again */
-            if (SafeTimeOut.QuadPart < 0)
+            if (LocalTimeOut.QuadPart < 0)
             {
                 /* Query the new time */
                 KeQuerySystemTime(&NewTime);
 
                 /* Substract times */
-                SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
+                LocalTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
                 StartTime = NewTime;
 
                 /* Check if we've timed out */
-                if (SafeTimeOut.QuadPart >= 0)
+                if (LocalTimeOut.QuadPart >= 0)
                 {
                     /* We have, break out of the loop */
                     Status = STATUS_TIMEOUT;
@@ -2032,20 +2157,18 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
     ObDereferenceObject(DebugObject);
 
     /* Protect write with SEH */
-    _SEH_TRY
+    _SEH2_TRY
     {
         /* Return our wait state change structure */
         *StateChange = WaitStateChange;
     }
-    _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+    _SEH2_EXCEPT(ExSystemExceptionFilter())
     {
         /* Get SEH Exception code */
-        Status = _SEH_GetExceptionCode();
+        Status = _SEH2_GetExceptionCode();
     }
-    _SEH_END;
+    _SEH2_END;
 
     /* Return status */
     return Status;
 }
-
-/* EOF */