- KDBG: Correct the use of PsLookupThread/ProcessByThread/ProcessId -- the caller...
[reactos.git] / reactos / ntoskrnl / kdbg / kdb.c
index 3391e76..2155e40 100644 (file)
@@ -6,12 +6,12 @@
  *
  * PROGRAMMERS:     Gregor Anich
  */
-      
+
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* TYPES *********************************************************************/
 
@@ -51,13 +51,14 @@ PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe
 STATIC KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } };  /* The trapframe which was passed to KdbEnterDebuggerException */
 STATIC KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
 STATIC KAPC_STATE KdbApcState;
+extern BOOLEAN KdbpBugCheckRequested;
 
 /* Array of conditions when to enter KDB */
 STATIC KDB_ENTER_CONDITION KdbEnterConditions[][2] =
 {
    /* First chance       Last chance */
    { KdbDoNotEnter,      KdbEnterFromKmode },   /* Zero devide */
-   { KdbEnterAlways,     KdbDoNotEnter },       /* Debug trap */
+   { KdbEnterFromKmode,  KdbDoNotEnter },       /* Debug trap */
    { KdbDoNotEnter,      KdbEnterAlways },      /* NMI */
    { KdbEnterFromKmode,  KdbDoNotEnter },       /* INT3 */
    { KdbDoNotEnter,      KdbEnterFromKmode },   /* Overflow */
@@ -80,7 +81,7 @@ STATIC KDB_ENTER_CONDITION KdbEnterConditions[][2] =
 };
 
 /* Exception descriptions */
-STATIC CONST PCHAR ExceptionNrToString[] =
+STATIC CONST CHAR *ExceptionNrToString[] =
 {
    "Divide Error",
    "Debug Trap",
@@ -122,25 +123,58 @@ NTAPI
 KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
                  IN ULONG Esp);
 
+/* ROS Internal. Please deprecate */
+NTHALAPI
+VOID
+NTAPI
+HalReleaseDisplayOwnership(
+    VOID
+);
+
 /* FUNCTIONS *****************************************************************/
 
 STATIC VOID
 KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
 {
+   ULONG TrapCr0, TrapCr2, TrapCr3, TrapCr4;
+
    /* Copy the TrapFrame only up to Eflags and zero the rest*/
-   RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, Esp));
-   RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, Esp)),
-                 sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, Esp));
+   RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+   RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, HardwareEsp)),
+                 sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+
+#ifndef _MSC_VER
    asm volatile(
       "movl %%cr0, %0"    "\n\t"
       "movl %%cr2, %1"    "\n\t"
       "movl %%cr3, %2"    "\n\t"
       "movl %%cr4, %3"    "\n\t"
-      : "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
-        "=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
+      : "=r"(TrapCr0), "=r"(TrapCr2),
+        "=r"(TrapCr3), "=r"(TrapCr4));
+#else
+   __asm
+   {
+       mov eax, cr0;
+       mov TrapCr0, eax;
+
+       mov eax, cr2;
+       mov TrapCr2, eax;
+
+       mov eax, cr3;
+       mov TrapCr3, eax;
+/* FIXME: What's the problem with cr4? */
+       //mov eax, cr4;
+       //mov TrapCr4, eax;
+   }
+#endif
 
-    KdbTrapFrame->Tf.Esp = KiEspFromTrapFrame(TrapFrame);
-    KdbTrapFrame->Tf.Ss = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
+    KdbTrapFrame->Cr0 = TrapCr0;
+    KdbTrapFrame->Cr2 = TrapCr2;
+    KdbTrapFrame->Cr3 = TrapCr3;
+    KdbTrapFrame->Cr4 = TrapCr4;
+
+    KdbTrapFrame->Tf.HardwareEsp = KiEspFromTrapFrame(TrapFrame);
+    KdbTrapFrame->Tf.HardwareSegSs = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
 
 
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
@@ -150,16 +184,39 @@ STATIC VOID
 KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFrame)
 {
    /* Copy the TrapFrame only up to Eflags and zero the rest*/
-   RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, Esp));
-   
+   RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
+
    /* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
-   
-    KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Ss);
-    KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Esp);
-   
+
+    KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareSegSs);
+    KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareEsp);
+
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
 
+STATIC VOID
+KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack,
+                                PKDB_KTRAP_FRAME KdbTrapFrame)
+{
+   ULONG_PTR *StackPtr;
+
+   RtlZeroMemory(KdbTrapFrame, sizeof(KDB_KTRAP_FRAME));
+   StackPtr = (ULONG_PTR *) KernelStack;
+   KdbTrapFrame->Tf.Ebp = StackPtr[3];
+   KdbTrapFrame->Tf.Edi = StackPtr[4];
+   KdbTrapFrame->Tf.Esi = StackPtr[5];
+   KdbTrapFrame->Tf.Ebx = StackPtr[6];
+   KdbTrapFrame->Tf.Eip = StackPtr[7];
+   KdbTrapFrame->Tf.HardwareEsp = (ULONG) (StackPtr + 8);
+   KdbTrapFrame->Tf.HardwareSegSs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegCs = KGDT_R0_CODE;
+   KdbTrapFrame->Tf.SegDs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegEs = KGDT_R0_DATA;
+   KdbTrapFrame->Tf.SegGs = KGDT_R0_DATA;
+
+   /* FIXME: what about the other registers??? */
+}
+
 /*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
  *        the old instruction in *OldInst.
  *
@@ -251,7 +308,7 @@ BOOLEAN
 KdbpShouldStepOverInstruction(ULONG_PTR Eip)
 {
    UCHAR Mem[3];
-   UINT i = 0;
+   ULONG i = 0;
 
    if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
    {
@@ -311,7 +368,7 @@ KdbpStepOverInstruction(ULONG_PTR Eip)
 BOOLEAN
 KdbpStepIntoInstruction(ULONG_PTR Eip)
 {
-   KDESCRIPTOR Idtr;
+    KDESCRIPTOR Idtr = {0};
    UCHAR Mem[2];
    INT IntVect;
    ULONG IntDesc[2];
@@ -330,7 +387,7 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
       IntVect = 3;
    else if (Mem[0] == 0xcd)
       IntVect = Mem[1];
-   else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.Eflags & (1<<11)) /* 1 << 11 is the overflow flag */
+   else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
       IntVect = 4;
    else
       return FALSE;
@@ -341,7 +398,7 @@ KdbpStepIntoInstruction(ULONG_PTR Eip)
    }
 
    /* Read the interrupt descriptor table register  */
-   asm volatile("sidt %0" : : "m"(Idtr.Limit));
+   Ke386GetInterruptDescriptorTable(*(PKDESCRIPTOR)&Idtr.Limit);
    if (IntVect >= (Idtr.Limit + 1) / 8)
    {
       /*KdbpPrint("IDT does not contain interrupt vector %d\n.", IntVect);*/
@@ -484,7 +541,7 @@ KdbpInsertBreakPoint(
    IN  KDB_ACCESS_TYPE AccessType  OPTIONAL,
    IN  PCHAR ConditionExpression  OPTIONAL,
    IN  BOOLEAN Global,
-   OUT PULONG BreakPointNumber  OPTIONAL)
+   OUT PLONG BreakPointNr  OPTIONAL)
 {
    LONG i;
    PVOID Condition;
@@ -580,8 +637,8 @@ KdbpInsertBreakPoint(
    KdbpEnableBreakPoint(i, NULL);
 
    /* Return the breakpoint number */
-   if (BreakPointNumber != NULL)
-      *BreakPointNumber = i;
+   if (BreakPointNr != NULL)
+      *BreakPointNr = i;
 
    return STATUS_SUCCESS;
 }
@@ -643,13 +700,13 @@ KdbpDeleteBreakPoint(
  */
 STATIC LONG
 KdbpIsBreakPointOurs(
-   IN ULONG ExpNr,
+   IN NTSTATUS ExceptionCode,
    IN PKTRAP_FRAME TrapFrame)
 {
-   UINT i;
-   ASSERT(ExpNr == 1 || ExpNr == 3);
+   ULONG i;
+   ASSERT(ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT);
 
-   if (ExpNr == 3) /* Software interrupt */
+   if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
    {
       ULONG_PTR BpEip = (ULONG_PTR)TrapFrame->Eip - 1; /* Get EIP of INT3 instruction */
       for (i = 0; i < KdbSwBreakPointCount; i++)
@@ -663,7 +720,7 @@ KdbpIsBreakPointOurs(
          }
       }
    }
-   else if (ExpNr == 1) /* Hardware interrupt */
+   else if (ExceptionCode == STATUS_SINGLE_STEP) /* Hardware interrupt */
    {
       UCHAR DebugReg;
       for (i = 0; i < KdbHwBreakPointCount; i++)
@@ -852,7 +909,7 @@ KdbpDisableBreakPoint(
    IN LONG BreakPointNr  OPTIONAL,
    IN OUT PKDB_BREAKPOINT BreakPoint  OPTIONAL)
 {
-   UINT i;
+   ULONG i;
    NTSTATUS Status;
 
    if (BreakPointNr < 0)
@@ -902,7 +959,7 @@ KdbpDisableBreakPoint(
             break;
          }
       }
-      if (i != (UINT)-1) /* not found */
+      if (i != (ULONG)-1) /* not found */
          ASSERT(0);
    }
    else
@@ -928,7 +985,7 @@ KdbpDisableBreakPoint(
             break;
          }
       }
-      if (i != (UINT)-1) /* not found */
+      if (i != (ULONG)-1) /* not found */
          ASSERT(0);
    }
 
@@ -1017,7 +1074,7 @@ KdbpAttachToThread(
    /* Get a pointer to the thread */
    if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
    {
-      KdbpPrint("Invalid thread id: 0x%08x\n", (UINT)ThreadId);
+      KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG)ThreadId);
       return FALSE;
    }
    Process = Thread->ThreadsProcess;
@@ -1025,6 +1082,7 @@ KdbpAttachToThread(
    if (KeIsExecutingDpc() && Process != KdbCurrentProcess)
    {
       KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
+      ObDereferenceObject(Thread);
       return FALSE;
    }
 
@@ -1032,7 +1090,8 @@ KdbpAttachToThread(
    if (KdbCurrentThread != KdbOriginalThread)
    {
       ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
-      KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
+      /* Actually, we can't save the context, there's no guarantee that there
+       * was a trap frame */
    }
    else
    {
@@ -1042,12 +1101,13 @@ KdbpAttachToThread(
    /* Switch to the thread's context */
    if (Thread != KdbOriginalThread)
    {
-      if (Thread->Tcb.TrapFrame == NULL)
-      {
-         KdbpPrint("Threads TrapFrame is NULL! Cannot attach.\n");
-         return FALSE;
-      }
-      KdbpTrapFrameToKdbTrapFrame(Thread->Tcb.TrapFrame, &KdbThreadTrapFrame);
+      /* The thread we're attaching to isn't the thread on which we entered
+       * kdb and so the thread we're attaching to is not running. There
+       * is no guarantee that it actually has a trap frame. So we have to
+       * peek directly at the registers which were saved on the stack when the
+       * thread was preempted in the scheduler */
+      KdbpKdbTrapFrameFromKernelStack(Thread->Tcb.KernelStack,
+                                      &KdbThreadTrapFrame);
       KdbCurrentTrapFrame = &KdbThreadTrapFrame;
    }
    else /* Switching back to original thread */
@@ -1071,6 +1131,7 @@ KdbpAttachToThread(
       KdbCurrentProcess = Process;
    }
 
+   ObDereferenceObject(Thread);
    return TRUE;
 }
 
@@ -1094,14 +1155,15 @@ KdbpAttachToProcess(
    /* Get a pointer to the process */
    if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)))
    {
-      KdbpPrint("Invalid process id: 0x%08x\n", (UINT)ProcessId);
+      KdbpPrint("Invalid process id: 0x%08x\n", (ULONG)ProcessId);
       return FALSE;
    }
 
    Entry = Process->ThreadListHead.Flink;
+   ObDereferenceObject(Process);
    if (Entry == &KdbCurrentProcess->ThreadListHead)
    {
-      KdbpPrint("No threads in process 0x%08x, cannot attach to process!\n", (UINT)ProcessId);
+      KdbpPrint("No threads in process 0x%08x, cannot attach to process!\n", (ULONG)ProcessId);
       return FALSE;
    }
 
@@ -1132,7 +1194,7 @@ KdbpInternalEnter()
    KbdDisableMouse();
    if (KdpDebugMode.Screen)
    {
-      HalReleaseDisplayOwnership();
+      InbvAcquireDisplayOwnership();
    }
 
    /* Call the interface's main loop on a different stack */
@@ -1145,9 +1207,9 @@ KdbpInternalEnter()
    Thread->Tcb.StackLimit = (ULONG)KdbStack;
    Thread->Tcb.KernelStack = (char*)KdbStack + KDB_STACK_SIZE;
 
-   /*KdbpPrint("Switching to KDB stack 0x%08x-0x%08x\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase);*/
+   /*KdbpPrint("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp);*/
 
-   KdbpStackSwitchAndCall(Thread->Tcb.KernelStack, KdbpCallMainLoop);
+   KdbpStackSwitchAndCall(KdbStack + KDB_STACK_SIZE - sizeof(ULONG), KdbpCallMainLoop);
 
    Thread->Tcb.InitialStack = SavedInitialStack;
    Thread->Tcb.StackBase = SavedStackBase;
@@ -1156,13 +1218,62 @@ KdbpInternalEnter()
    KbdEnableMouse();
 }
 
+STATIC ULONG
+KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
+{
+    ULONG Ret;
+
+    switch (ExceptionCode)
+    {
+        case STATUS_INTEGER_DIVIDE_BY_ZERO:
+            Ret = 0;
+            break;
+        case STATUS_SINGLE_STEP:
+            Ret = 1;
+            break;
+        case STATUS_BREAKPOINT:
+            Ret = 3;
+            break;
+        case STATUS_INTEGER_OVERFLOW:
+            Ret = 4;
+            break;
+        case STATUS_ARRAY_BOUNDS_EXCEEDED:
+            Ret = 5;
+            break;
+        case STATUS_ILLEGAL_INSTRUCTION:
+            Ret = 6;
+            break;
+        case STATUS_FLOAT_INVALID_OPERATION:
+            Ret = 7;
+            break;
+        case STATUS_STACK_OVERFLOW:
+            Ret = 12;
+            break;
+        case STATUS_ACCESS_VIOLATION:
+            Ret = 14;
+            break;
+        case STATUS_DATATYPE_MISALIGNMENT:
+            Ret = 17;
+            break;
+        case STATUS_FLOAT_MULTIPLE_TRAPS:
+            Ret = 18;
+            break;
+
+        default:
+            Ret = RTL_NUMBER_OF(KdbEnterConditions) - 1;
+            break;
+    }
+
+    return Ret;
+}
+
 /*!\brief KDB Exception filter
  *
  * Called by the exception dispatcher.
  *
  * \param ExceptionRecord  Unused.
  * \param PreviousMode     UserMode if the exception was raised from umode, otherwise KernelMode.
- * \param Context          Unused.
+ * \param Context          Context, IN/OUT parameter.
  * \param TrapFrame        Exception TrapFrame.
  * \param FirstChance      TRUE when called before exception frames were serached,
  *                         FALSE for the second call.
@@ -1173,29 +1284,32 @@ KD_CONTINUE_TYPE
 KdbEnterDebuggerException(
    IN PEXCEPTION_RECORD ExceptionRecord  OPTIONAL,
    IN KPROCESSOR_MODE PreviousMode,
-   IN PCONTEXT Context  OPTIONAL,
+   IN PCONTEXT Context,
    IN OUT PKTRAP_FRAME TrapFrame,
    IN BOOLEAN FirstChance)
 {
-   ULONG ExpNr = (ULONG)TrapFrame->DebugArgMark;
    KDB_ENTER_CONDITION EnterCondition;
    KD_CONTINUE_TYPE ContinueType = kdHandleException;
    PKDB_BREAKPOINT BreakPoint;
-   ULONG ul;
+   ULONG ExpNr;
    ULONGLONG ull;
    BOOLEAN Resume = FALSE;
    BOOLEAN EnterConditionMet = TRUE;
    ULONG OldEflags;
+   NTSTATUS ExceptionCode;
+
+   ExceptionCode = (ExceptionRecord != NULL ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT);
 
    KdbCurrentProcess = PsGetCurrentProcess();
 
    /* Set continue type to kdContinue for single steps and breakpoints */
-   if (ExpNr == 1 || ExpNr == 3)
+   if (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT)
       ContinueType = kdContinue;
 
    /* Check if we should handle the exception. */
-   ul = min(ExpNr, RTL_NUMBER_OF(KdbEnterConditions) - 1);
-   EnterCondition = KdbEnterConditions[ul][FirstChance ? 0 : 1];
+   /* FIXME - won't get all exceptions here :( */
+   ExpNr = KdbpGetExceptionNumberFromStatus(ExceptionCode);
+   EnterCondition = KdbEnterConditions[ExpNr][FirstChance ? 0 : 1];
    if (EnterCondition == KdbDoNotEnter ||
        (EnterCondition == KdbEnterFromUmode && PreviousMode == KernelMode) ||
        (EnterCondition == KdbEnterFromKmode && PreviousMode != KernelMode))
@@ -1207,27 +1321,21 @@ KdbEnterDebuggerException(
    KdbLastBreakPointNr = -1;
    KdbEnteredOnSingleStep = FALSE;
 
-   if (FirstChance && (ExpNr == 1 || ExpNr == 3) &&
-       (KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExpNr, TrapFrame)) >= 0)
+   if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
+       (KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExceptionCode, TrapFrame)) >= 0)
    {
       BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
 
-      if (ExpNr == 3)
+      if (ExceptionCode == STATUS_BREAKPOINT)
       {
-         /*
-          * The breakpoint will point to the next instruction by default so
-          * point it back to the start of original instruction.
-          */
-         TrapFrame->Eip--;
-
          /*
           * ... and restore the original instruction.
           */
          if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address,
                                                   BreakPoint->Data.SavedInstruction, NULL)))
          {
-            DbgPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
-            KEBUGCHECK(0);
+            KdbpPrint("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
+            KeBugCheck(0); // FIXME: Proper bugcode!
          }
       }
 
@@ -1245,7 +1353,7 @@ KdbEnterDebuggerException(
       else if (BreakPoint->Type == KdbBreakPointTemporary &&
                BreakPoint->Process == KdbCurrentProcess)
       {
-         ASSERT((TrapFrame->Eflags & X86_EFLAGS_TF) == 0);
+         ASSERT((TrapFrame->EFlags & EFLAGS_TF) == 0);
 
          /*
           * Delete the temporary breakpoint which was used to step over or into the instruction.
@@ -1257,7 +1365,7 @@ KdbEnterDebuggerException(
             if ((KdbSingleStepOver && !KdbpStepOverInstruction(TrapFrame->Eip)) ||
                 (!KdbSingleStepOver && !KdbpStepIntoInstruction(TrapFrame->Eip)))
             {
-               TrapFrame->Eflags |= X86_EFLAGS_TF;
+               Context->EFlags |= EFLAGS_TF;
             }
             goto continue_execution; /* return */
          }
@@ -1272,8 +1380,8 @@ KdbEnterDebuggerException(
       else if (BreakPoint->Type == KdbBreakPointSoftware ||
                BreakPoint->Type == KdbBreakPointTemporary)
       {
-         ASSERT(ExpNr == 3);
-         TrapFrame->Eflags |= X86_EFLAGS_TF;
+         ASSERT(ExceptionCode == STATUS_BREAKPOINT);
+         Context->EFlags |= EFLAGS_TF;
          KdbBreakPointToReenable = BreakPoint;
       }
 
@@ -1306,12 +1414,12 @@ KdbEnterDebuggerException(
 
       if (BreakPoint->Type == KdbBreakPointSoftware)
       {
-         DbgPrint("Entered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
-                  KdbLastBreakPointNr, TrapFrame->Cs & 0xffff, TrapFrame->Eip);
+         KdbpPrint("Entered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
+                  KdbLastBreakPointNr, TrapFrame->SegCs & 0xffff, TrapFrame->Eip);
       }
       else if (BreakPoint->Type == KdbBreakPointHardware)
       {
-         DbgPrint("Entered debugger on breakpoint #%d: %s 0x%08x\n",
+         KdbpPrint("Entered debugger on breakpoint #%d: %s 0x%08x\n",
                   KdbLastBreakPointNr,
                   (BreakPoint->Data.Hw.AccessType == KdbAccessRead) ? "READ" :
                   ((BreakPoint->Data.Hw.AccessType == KdbAccessWrite) ? "WRITE" :
@@ -1322,7 +1430,7 @@ KdbEnterDebuggerException(
 
       }
    }
-   else if (ExpNr == 1)
+   else if (ExceptionCode == STATUS_SINGLE_STEP)
    {
       /* Silently ignore a debugger initiated single step. */
       if ((TrapFrame->Dr6 & 0xf) == 0 && KdbBreakPointToReenable != NULL)
@@ -1340,47 +1448,49 @@ KdbEnterDebuggerException(
          if (!NT_SUCCESS(KdbpOverwriteInstruction(KdbCurrentProcess, BreakPoint->Address, 0xCC,
                                                   &BreakPoint->Data.SavedInstruction)))
          {
-            DbgPrint("Warning: Couldn't reenable breakpoint %d\n",
+            KdbpPrint("Warning: Couldn't reenable breakpoint %d\n",
                      BreakPoint - KdbBreakPoints);
          }
 
          /* Unset TF if we are no longer single stepping. */
          if (KdbNumSingleSteps == 0)
-            TrapFrame->Eflags &= ~X86_EFLAGS_TF;
+            Context->EFlags &= ~EFLAGS_TF;
          goto continue_execution; /* return */
       }
 
       /* Check if we expect a single step */
       if ((TrapFrame->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
       {
-         /*ASSERT((TrapFrame->Eflags & X86_EFLAGS_TF) != 0);*/
+         /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
          if (--KdbNumSingleSteps > 0)
          {
             if ((KdbSingleStepOver && KdbpStepOverInstruction(TrapFrame->Eip)) ||
                 (!KdbSingleStepOver && KdbpStepIntoInstruction(TrapFrame->Eip)))
             {
-               TrapFrame->Eflags &= ~X86_EFLAGS_TF;
+               Context->EFlags &= ~EFLAGS_TF;
             }
             else
             {
-               TrapFrame->Eflags |= X86_EFLAGS_TF;
+               Context->EFlags |= EFLAGS_TF;
             }
-            goto continue_execution; /* return */
+                       goto continue_execution; /* return */
          }
-
-         TrapFrame->Eflags &= ~X86_EFLAGS_TF;
-         KdbEnteredOnSingleStep = TRUE;
+                else 
+                {
+                        Context->EFlags &= ~EFLAGS_TF;
+                        KdbEnteredOnSingleStep = TRUE;
+                }
       }
       else
       {
          if (!EnterConditionMet)
          {
-            return ContinueType;
+            return kdHandleException;
          }
-         DbgPrint("Entered debugger on unexpected debug trap!\n");
+         KdbpPrint("Entered debugger on unexpected debug trap!\n");
       }
    }
-   else if (ExpNr == 3)
+   else if (ExceptionCode == STATUS_BREAKPOINT)
    {
       if (KdbInitFileBuffer != NULL)
       {
@@ -1389,15 +1499,15 @@ KdbEnterDebuggerException(
       }
       if (!EnterConditionMet)
       {
-         return ContinueType;
+         return kdHandleException;
       }
 
-      DbgPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
-               TrapFrame->Cs & 0xffff, TrapFrame->Eip - 1);
+      KdbpPrint("Entered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
+               TrapFrame->SegCs & 0xffff, TrapFrame->Eip - 1);
    }
    else
    {
-      CONST PCHAR ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
+      CONST CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
                                     (ExceptionNrToString[ExpNr]) :
                                     ("Unknown/User defined exception");
 
@@ -1406,24 +1516,33 @@ KdbEnterDebuggerException(
          return ContinueType;
       }
 
-      DbgPrint("Entered debugger on %s-chance exception number %d (%s)\n",
-               FirstChance ? "first" : "last", ExpNr, ExceptionString);
-      if (ExpNr == 14)
+      KdbpPrint("Entered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
+               FirstChance ? "first" : "last", ExceptionCode, ExceptionString);
+      if (ExceptionCode == STATUS_ACCESS_VIOLATION &&
+          ExceptionRecord != NULL && ExceptionRecord->NumberParameters != 0)
       {
          /* FIXME: Add noexec memory stuff */
-         ULONG_PTR Cr2;
+         ULONG_PTR TrapCr2;
          ULONG Err;
-         asm volatile("movl %%cr2, %0" : "=r"(Cr2));
-         Err = TrapFrame->ErrorCode;
-         DbgPrint("Memory at 0x%p could not be %s: ", Cr2, (Err & (1 << 1)) ? "written" : "read");
+#ifdef __GNUC__
+         asm volatile("movl %%cr2, %0" : "=r"(TrapCr2));
+#elif _MSC_VER
+         __asm mov eax, cr2;
+         __asm mov TrapCr2, eax;
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+         Err = TrapFrame->ErrCode;
+         KdbpPrint("Memory at 0x%p could not be %s: ", TrapCr2, (Err & (1 << 1)) ? "written" : "read");
          if ((Err & (1 << 0)) == 0)
-            DbgPrint("Page not present.\n");
+            KdbpPrint("Page not present.\n");
          else
          {
             if ((Err & (1 << 3)) != 0)
-               DbgPrint("Reserved bits in page directory set.\n");
+               KdbpPrint("Reserved bits in page directory set.\n");
             else
-               DbgPrint("Page protection violation.\n");
+               KdbpPrint("Page protection violation.\n");
          }
       }
    }
@@ -1441,7 +1560,7 @@ KdbEnterDebuggerException(
 
    /* Enter critical section */
    Ke386SaveFlags(OldEflags);
-   Ke386DisableInterrupts();
+   _disable();
 
    /* Exception inside the debugger? Game over. */
    if (InterlockedIncrement(&KdbEntryCount) > 1)
@@ -1459,20 +1578,17 @@ KdbEnterDebuggerException(
       if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Tf.Eip)) ||
           (!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Tf.Eip)))
       {
-         ASSERT((KdbCurrentTrapFrame->Tf.Eflags & X86_EFLAGS_TF) == 0);
-         /*KdbCurrentTrapFrame->Tf.Eflags &= ~X86_EFLAGS_TF;*/
+         ASSERT((KdbCurrentTrapFrame->Tf.EFlags & EFLAGS_TF) == 0);
+         /*KdbCurrentTrapFrame->Tf.EFlags &= ~EFLAGS_TF;*/
       }
       else
       {
-         KdbCurrentTrapFrame->Tf.Eflags |= X86_EFLAGS_TF;
+         Context->EFlags |= EFLAGS_TF;
       }
    }
 
-   /* Save the current thread's trapframe */
-   if (KdbCurrentTrapFrame == &KdbThreadTrapFrame)
-   {
-      KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
-   }
+   /* We can't update the current thread's trapframe 'cause it might not
+      have one */
 
    /* Detach from attached process */
    if (KdbCurrentProcess != KdbOriginalProcess)
@@ -1489,19 +1605,29 @@ KdbEnterDebuggerException(
    /* Leave critical section */
    Ke386RestoreFlags(OldEflags);
 
+   /* Check if user requested a bugcheck */
+   if (KdbpBugCheckRequested)
+   {
+       /* Clear the flag and bugcheck the system */
+       KdbpBugCheckRequested = FALSE;
+       KeBugCheck(MANUALLY_INITIATED_CRASH);
+   }
+
 continue_execution:
    /* Clear debug status */
-   if (ExpNr == 1 || ExpNr == 3) /* FIXME: Why clear DR6 on INT3? */
+   if (ExceptionCode == STATUS_BREAKPOINT) /* FIXME: Why clear DR6 on INT3? */
    {
       /* Set the RF flag so we don't trigger the same breakpoint again. */
       if (Resume)
       {
-         TrapFrame->Eflags |= X86_EFLAGS_RF;
+         TrapFrame->EFlags |= EFLAGS_RF;
       }
 
       /* Clear dr6 status flags. */
       TrapFrame->Dr6 &= ~0x0000e00f;
 
+      /* Skip the current instruction */
+      Context->Eip++;
    }
 
    return ContinueType;
@@ -1516,12 +1642,12 @@ KdbDeleteProcessHook(IN PEPROCESS Process)
 }
 
 VOID
-STDCALL
+NTAPI
 KdbpGetCommandLineSettings(PCHAR p1)
 {
     PCHAR p2;
 
-    while (p1 && (p2 = strchr(p1, '/')))
+    while (p1 && (p2 = strchr(p1, ' ')))
     {
         p2++;
 
@@ -1546,21 +1672,31 @@ KdbpSafeReadMemory(OUT PVOID Dest,
                    IN PVOID Src,
                    IN ULONG Bytes)
 {
-   NTSTATUS Status = STATUS_SUCCESS;
+    BOOLEAN Result = TRUE;
 
-   _SEH_TRY
-   {
-      RtlCopyMemory(Dest,
-                    Src,
-                    Bytes);
-   }
-   _SEH_HANDLE
-   {
-      Status = _SEH_GetExceptionCode();
-   }
-   _SEH_END;
-   
-   return Status;
+    switch (Bytes)
+    {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+        Result = KdpSafeReadMemory((ULONG_PTR)Src, Bytes, Dest);
+        break;
+    default:
+    {
+        ULONG_PTR Start, End, Write;
+        for (Start = (ULONG_PTR)Src, 
+                 End = Start + Bytes, 
+                 Write = (ULONG_PTR)Dest; 
+             Result && (Start < End); 
+             Start++, Write++)
+            if (!KdpSafeReadMemory(Start, 1, (PVOID)Write))
+                Result = FALSE;
+        break;
+    }
+    }
+
+    return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
 }
 
 NTSTATUS
@@ -1568,19 +1704,16 @@ KdbpSafeWriteMemory(OUT PVOID Dest,
                     IN PVOID Src,
                     IN ULONG Bytes)
 {
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   _SEH_TRY
-   {
-      RtlCopyMemory(Dest,
-                    Src,
-                    Bytes);
-   }
-   _SEH_HANDLE
-   {
-      Status = _SEH_GetExceptionCode();
-   }
-   _SEH_END;
-
-   return Status;
+    BOOLEAN Result = TRUE;
+    ULONG_PTR Start, End, Write;
+
+    for (Start = (ULONG_PTR)Src, 
+             End = Start + Bytes, 
+             Write = (ULONG_PTR)Dest; 
+         Result && (Start < End); 
+         Start++, Write++)
+        if (!KdpSafeWriteMemory(Write, 1, *((PCHAR)Start)))
+            Result = FALSE;
+
+    return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
 }