- KDBG: Correct the use of PsLookupThread/ProcessByThread/ProcessId -- the caller...
[reactos.git] / reactos / ntoskrnl / kdbg / kdb_cli.c
index 8e4e13a..58d08a7 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- *
+/*
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/dbg/kdb_cli.c
  * PURPOSE:         Kernel debugger command line interface
  * PROGRAMMER:      Gregor Anich (blight@blight.eu.org)
+ *                  HervĂ© Poussineau
  * UPDATE HISTORY:
  *                  Created 16/01/2005
  */
 #include <ntoskrnl.h>
 
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* DEFINES *******************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 #define KEY_BS          8
 #define KEY_ESC         27
 #define KEY_DEL         127
@@ -57,9 +53,8 @@
                    ((type) == KdbAccessReadWrite ? "rdwr" : "exec")))
 
 #define NPX_STATE_TO_STRING(state)                                        \
-                   ((state) == NPX_STATE_INVALID ? "Invalid" :            \
-                   ((state) == NPX_STATE_VALID ? "Valid" :                \
-                   ((state) == NPX_STATE_DIRTY ? "Dirty" : "Unknown")))
+                   ((state) == NPX_STATE_LOADED ? "Loaded" :              \
+                   ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown"))
 
 /* PROTOTYPES ****************************************************************/
 
@@ -83,12 +78,14 @@ STATIC BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]);
 STATIC BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
 
 STATIC BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
+STATIC BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
 STATIC BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
 STATIC BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
 
 /* GLOBALS *******************************************************************/
 
 STATIC BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
+STATIC BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
 
 STATIC CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
 STATIC PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
@@ -102,6 +99,7 @@ STATIC LONG KdbNumberOfRowsTerminal = -1;
 STATIC LONG KdbNumberOfColsTerminal = -1;
 
 PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
+BOOLEAN KdbpBugCheckRequested = FALSE;
 
 STATIC CONST struct
 {
@@ -150,12 +148,139 @@ STATIC CONST struct
    /* Others */
    { NULL, NULL, "Others", NULL },
    { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
+   { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels", KdbpCmdFilter },
    { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
    { "help", "help", "Display help screen.", KdbpCmdHelp }
 };
 
 /* FUNCTIONS *****************************************************************/
 
+/*!\brief Transform a component name to an integer
+ *
+ * \param ComponentName  The name of the component.
+ * \param ComponentId    Receives the component id on success.
+ *
+ * \retval TRUE   Success.
+ * \retval FALSE  Failure.
+ */
+STATIC BOOLEAN
+KdbpGetComponentId(
+   IN  PCCH ComponentName,
+   OUT PULONG ComponentId)
+{
+   ULONG i;
+
+   static struct {
+      PCCH Name;
+      ULONG Id;
+   } ComponentTable[] = {
+       { "DEFAULT", DPFLTR_DEFAULT_ID },
+       { "SYSTEM", DPFLTR_SYSTEM_ID },
+       { "SMSS", DPFLTR_SMSS_ID },
+       { "SETUP", DPFLTR_SETUP_ID },
+       { "NTFS", DPFLTR_NTFS_ID },
+       { "FSTUB", DPFLTR_FSTUB_ID },
+       { "CRASHDUMP", DPFLTR_CRASHDUMP_ID },
+       { "CDAUDIO", DPFLTR_CDAUDIO_ID },
+       { "CDROM", DPFLTR_CDROM_ID },
+       { "CLASSPNP", DPFLTR_CLASSPNP_ID },
+       { "DISK", DPFLTR_DISK_ID },
+       { "REDBOOK", DPFLTR_REDBOOK_ID },
+       { "STORPROP", DPFLTR_STORPROP_ID },
+       { "SCSIPORT", DPFLTR_SCSIPORT_ID },
+       { "SCSIMINIPORT", DPFLTR_SCSIMINIPORT_ID },
+       { "CONFIG", DPFLTR_CONFIG_ID },
+       { "I8042PRT", DPFLTR_I8042PRT_ID },
+       { "SERMOUSE", DPFLTR_SERMOUSE_ID },
+       { "LSERMOUS", DPFLTR_LSERMOUS_ID },
+       { "KBDHID", DPFLTR_KBDHID_ID },
+       { "MOUHID", DPFLTR_MOUHID_ID },
+       { "KBDCLASS", DPFLTR_KBDCLASS_ID },
+       { "MOUCLASS", DPFLTR_MOUCLASS_ID },
+       { "TWOTRACK", DPFLTR_TWOTRACK_ID },
+       { "WMILIB", DPFLTR_WMILIB_ID },
+       { "ACPI", DPFLTR_ACPI_ID },
+       { "AMLI", DPFLTR_AMLI_ID },
+       { "HALIA64", DPFLTR_HALIA64_ID },
+       { "VIDEO", DPFLTR_VIDEO_ID },
+       { "SVCHOST", DPFLTR_SVCHOST_ID },
+       { "VIDEOPRT", DPFLTR_VIDEOPRT_ID },
+       { "TCPIP", DPFLTR_TCPIP_ID },
+       { "DMSYNTH", DPFLTR_DMSYNTH_ID },
+       { "NTOSPNP", DPFLTR_NTOSPNP_ID },
+       { "FASTFAT", DPFLTR_FASTFAT_ID },
+       { "SAMSS", DPFLTR_SAMSS_ID },
+       { "PNPMGR", DPFLTR_PNPMGR_ID },
+       { "NETAPI", DPFLTR_NETAPI_ID },
+       { "SCSERVER", DPFLTR_SCSERVER_ID },
+       { "SCCLIENT", DPFLTR_SCCLIENT_ID },
+       { "SERIAL", DPFLTR_SERIAL_ID },
+       { "SERENUM", DPFLTR_SERENUM_ID },
+       { "UHCD", DPFLTR_UHCD_ID },
+       { "BOOTOK", DPFLTR_BOOTOK_ID },
+       { "BOOTVRFY", DPFLTR_BOOTVRFY_ID },
+       { "RPCPROXY", DPFLTR_RPCPROXY_ID },
+       { "AUTOCHK", DPFLTR_AUTOCHK_ID },
+       { "DCOMSS", DPFLTR_DCOMSS_ID },
+       { "UNIMODEM", DPFLTR_UNIMODEM_ID },
+       { "SIS", DPFLTR_SIS_ID },
+       { "FLTMGR", DPFLTR_FLTMGR_ID },
+       { "WMICORE", DPFLTR_WMICORE_ID },
+       { "BURNENG", DPFLTR_BURNENG_ID },
+       { "IMAPI", DPFLTR_IMAPI_ID },
+       { "SXS", DPFLTR_SXS_ID },
+       { "FUSION", DPFLTR_FUSION_ID },
+       { "IDLETASK", DPFLTR_IDLETASK_ID },
+       { "SOFTPCI", DPFLTR_SOFTPCI_ID },
+       { "TAPE", DPFLTR_TAPE_ID },
+       { "MCHGR", DPFLTR_MCHGR_ID },
+       { "IDEP", DPFLTR_IDEP_ID },
+       { "PCIIDE", DPFLTR_PCIIDE_ID },
+       { "FLOPPY", DPFLTR_FLOPPY_ID },
+       { "FDC", DPFLTR_FDC_ID },
+       { "TERMSRV", DPFLTR_TERMSRV_ID },
+       { "W32TIME", DPFLTR_W32TIME_ID },
+       { "PREFETCHER", DPFLTR_PREFETCHER_ID },
+       { "RSFILTER", DPFLTR_RSFILTER_ID },
+       { "FCPORT", DPFLTR_FCPORT_ID },
+       { "PCI", DPFLTR_PCI_ID },
+       { "DMIO", DPFLTR_DMIO_ID },
+       { "DMCONFIG", DPFLTR_DMCONFIG_ID },
+       { "DMADMIN", DPFLTR_DMADMIN_ID },
+       { "WSOCKTRANSPORT", DPFLTR_WSOCKTRANSPORT_ID },
+       { "VSS", DPFLTR_VSS_ID },
+       { "PNPMEM", DPFLTR_PNPMEM_ID },
+       { "PROCESSOR", DPFLTR_PROCESSOR_ID },
+       { "DMSERVER", DPFLTR_DMSERVER_ID },
+       { "SR", DPFLTR_SR_ID },
+       { "INFINIBAND", DPFLTR_INFINIBAND_ID },
+       { "IHVDRIVER", DPFLTR_IHVDRIVER_ID },
+       { "IHVVIDEO", DPFLTR_IHVVIDEO_ID },
+       { "IHVAUDIO", DPFLTR_IHVAUDIO_ID },
+       { "IHVNETWORK", DPFLTR_IHVNETWORK_ID },
+       { "IHVSTREAMING", DPFLTR_IHVSTREAMING_ID },
+       { "IHVBUS", DPFLTR_IHVBUS_ID },
+       { "HPS", DPFLTR_HPS_ID },
+       { "RTLTHREADPOOL", DPFLTR_RTLTHREADPOOL_ID },
+       { "LDR", DPFLTR_LDR_ID },
+       { "TCPIP6", DPFLTR_TCPIP6_ID },
+       { "ISAPNP", DPFLTR_ISAPNP_ID },
+       { "SHPC", DPFLTR_SHPC_ID },
+       { "STORPORT", DPFLTR_STORPORT_ID },
+       { "STORMINIPORT", DPFLTR_STORMINIPORT_ID },
+       { "PRINTSPOOLER", DPFLTR_PRINTSPOOLER_ID },
+   };
+
+   for (i = 0; i < sizeof(ComponentTable) / sizeof(ComponentTable[0]); i++)
+       if (_stricmp(ComponentName, ComponentTable[i].Name) == 0)
+       {
+           *ComponentId = ComponentTable[i].Id;
+           return TRUE;
+       }
+
+   return FALSE;
+}
+
 /*!\brief Evaluates an expression...
  *
  * Much like KdbpRpnEvaluateExpression, but prints the error message (if any)
@@ -198,7 +323,7 @@ KdbpEvaluateExpression(
 STATIC BOOLEAN
 KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
 {
-   INT i, len;
+   ULONG i, len;
    ULONGLONG Result = 0;
    ULONG ul;
    LONG l = 0;
@@ -248,6 +373,85 @@ KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
    return TRUE;
 }
 
+/*!\brief Display list of active debug channels
+ */
+STATIC BOOLEAN
+KdbpCmdFilter(ULONG Argc, PCHAR Argv[])
+{
+    ULONG i, j, ComponentId, Level;
+    ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK;
+    PCHAR pend;
+    LPCSTR opt, p;
+    static struct {
+        LPCSTR Name;
+        ULONG Level;
+    } debug_classes[] = {
+        { "error", 1 << DPFLTR_ERROR_LEVEL },
+        { "warning", 1 << DPFLTR_WARNING_LEVEL },
+        { "trace", 1 << DPFLTR_TRACE_LEVEL },
+        { "info", 1 << DPFLTR_INFO_LEVEL },
+    };
+
+    for (i = 1; i < Argc; i++)
+    {
+        opt = Argv[i];
+        p = opt + strcspn(opt, "+-");
+        if (!p[0]) p = opt; /* assume it's a debug channel name */
+
+        if (p > opt)
+        {
+            for (j = 0; j < sizeof(debug_classes) / sizeof(debug_classes[0]); j++)
+            {
+                SIZE_T len = strlen(debug_classes[j].Name);
+                if (len != (p - opt))
+                    continue;
+                if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* found it */
+                {
+                    if (*p == '+')
+                        set |= debug_classes[j].Level;
+                    else
+                        clear |= debug_classes[j].Level;
+                    break;
+                }
+            }
+            if (j == sizeof(debug_classes) / sizeof(debug_classes[0]))
+            {
+                Level = strtoul(opt, &pend, 0);
+                if (pend != p)
+                {
+                    KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt);
+                    continue;
+                }
+                if (*p == '+')
+                    set |= Level;
+                else
+                    clear |= Level;
+            }
+        }
+        else
+        {
+            if (*p == '-')
+                clear = ~0;
+            else
+                set = ~0;
+        }
+        if (*p == '+' || *p == '-')
+            p++;
+
+        if (!KdbpGetComponentId(p, &ComponentId))
+        {
+            KdbpPrint("filter: '%s' is not a valid component name!\n", p);
+            return TRUE;
+        }
+
+        /* Get current mask value */
+        NtSetDebugFilterState(ComponentId, set, TRUE);
+        NtSetDebugFilterState(ComponentId, clear, FALSE);
+    }
+
+    return TRUE;
+}
+
 /*!\brief Disassembles 10 instructions at eip or given address or
  *        displays 16 dwords from memory at given address.
  */
@@ -382,28 +586,28 @@ KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
                 "   ECX  0x%08x   EDX  0x%08x\n"
                 "   ESI  0x%08x   EDI  0x%08x\n"
                 "   EBP  0x%08x\n",
-                Tf->Cs & 0xFFFF, Tf->Eip,
-                Tf->Ss, Tf->Esp,
+                Tf->SegCs & 0xFFFF, Tf->Eip,
+                Tf->HardwareSegSs, Tf->HardwareEsp,
                 Tf->Eax, Tf->Ebx,
                 Tf->Ecx, Tf->Edx,
                 Tf->Esi, Tf->Edi,
                 Tf->Ebp);
-      KdbpPrint("EFLAGS  0x%08x ", Tf->Eflags);
+      KdbpPrint("EFLAGS  0x%08x ", Tf->EFlags);
       for (i = 0; i < 32; i++)
       {
          if (i == 1)
          {
-            if ((Tf->Eflags & (1 << 1)) == 0)
+            if ((Tf->EFlags & (1 << 1)) == 0)
                KdbpPrint(" !BIT1");
          }
          else if (i == 12)
          {
-            KdbpPrint(" IOPL%d", (Tf->Eflags >> 12) & 3);
+            KdbpPrint(" IOPL%d", (Tf->EFlags >> 12) & 3);
          }
          else if (i == 13)
          {
          }
-         else if ((Tf->Eflags & (1 << i)) != 0)
+         else if ((Tf->EFlags & (1 << i)) != 0)
             KdbpPrint(EflagsBits[i]);
       }
       KdbpPrint("\n");
@@ -411,11 +615,8 @@ KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
    else if (Argv[0][0] == 'c') /* cregs */
    {
       ULONG Cr0, Cr2, Cr3, Cr4;
-      struct __attribute__((packed)) {
-         USHORT Limit;
-         ULONG Base;
-      } Gdtr, Ldtr, Idtr;
-      ULONG Tr;
+      KDESCRIPTOR Gdtr = {0}, Ldtr = {0}, Idtr = {0};
+      ULONG Tr = 0;
       STATIC CONST PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
                                          NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                          " WP", NULL, " AM", NULL, NULL, NULL, NULL, NULL,
@@ -431,12 +632,12 @@ KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
       Cr4 = KdbCurrentTrapFrame->Cr4;
 
       /* Get descriptor table regs */
-      asm volatile("sgdt %0" : : "m"(Gdtr));
-      asm volatile("sldt %0" : : "m"(Ldtr));
-      asm volatile("sidt %0" : : "m"(Idtr));
+      Ke386GetGlobalDescriptorTable(*(PKDESCRIPTOR)&Gdtr.Limit);
+      Ke386GetLocalDescriptorTable(Ldtr.Limit);
+      Ke386GetInterruptDescriptorTable(*(PKDESCRIPTOR)&Idtr.Limit);
 
       /* Get the task register */
-      asm volatile("str %0" : "=g"(Tr));
+      Ke386GetTr(Tr);
 
       /* Display the control registers */
       KdbpPrint("CR0  0x%08x ", Cr0);
@@ -467,18 +668,18 @@ KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
    else if (Argv[0][0] == 's') /* sregs */
    {
       KdbpPrint("CS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Cs & 0xffff, (Tf->Cs & 0xffff) >> 3,
-                (Tf->Cs & (1 << 2)) ? 'L' : 'G', Tf->Cs & 3);
+                Tf->SegCs & 0xffff, (Tf->SegCs & 0xffff) >> 3,
+                (Tf->SegCs & (1 << 2)) ? 'L' : 'G', Tf->SegCs & 3);
       KdbpPrint("DS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Ds, Tf->Ds >> 3, (Tf->Ds & (1 << 2)) ? 'L' : 'G', Tf->Ds & 3);
+                Tf->SegDs, Tf->SegDs >> 3, (Tf->SegDs & (1 << 2)) ? 'L' : 'G', Tf->SegDs & 3);
       KdbpPrint("ES  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Es, Tf->Es >> 3, (Tf->Es & (1 << 2)) ? 'L' : 'G', Tf->Es & 3);
+                Tf->SegEs, Tf->SegEs >> 3, (Tf->SegEs & (1 << 2)) ? 'L' : 'G', Tf->SegEs & 3);
       KdbpPrint("FS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Fs, Tf->Fs >> 3, (Tf->Fs & (1 << 2)) ? 'L' : 'G', Tf->Fs & 3);
+                Tf->SegFs, Tf->SegFs >> 3, (Tf->SegFs & (1 << 2)) ? 'L' : 'G', Tf->SegFs & 3);
       KdbpPrint("GS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Gs, Tf->Gs >> 3, (Tf->Gs & (1 << 2)) ? 'L' : 'G', Tf->Gs & 3);
+                Tf->SegGs, Tf->SegGs >> 3, (Tf->SegGs & (1 << 2)) ? 'L' : 'G', Tf->SegGs & 3);
       KdbpPrint("SS  0x%04x  Index 0x%04x  %cDT RPL%d\n",
-                Tf->Ss, Tf->Ss >> 3, (Tf->Ss & (1 << 2)) ? 'L' : 'G', Tf->Ss & 3);
+                Tf->HardwareSegSs, Tf->HardwareSegSs >> 3, (Tf->HardwareSegSs & (1 << 2)) ? 'L' : 'G', Tf->HardwareSegSs & 3);
    }
    else /* dregs */
    {
@@ -773,7 +974,8 @@ KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[])
    KDB_BREAKPOINT_TYPE Type;
    UCHAR Size = 0;
    KDB_ACCESS_TYPE AccessType = 0;
-   INT AddressArgIndex, ConditionArgIndex, i;
+   ULONG AddressArgIndex, i;
+   LONG ConditionArgIndex;
    BOOLEAN Global = TRUE;
 
    if (Argv[0][2] == 'x') /* software breakpoint */
@@ -888,6 +1090,7 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
    PLIST_ENTRY Entry;
    PETHREAD Thread = NULL;
    PEPROCESS Process = NULL;
+   BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE;
    PULONG Esp;
    PULONG Ebp;
    ULONG Eip;
@@ -916,6 +1119,9 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
             KdbpPrint("thread: Invalid process id!\n");
             return TRUE;
          }
+         
+         /* Remember our reference */
+         ReferencedProcess = TRUE;
       }
 
       Entry = Process->ThreadListHead.Flink;
@@ -925,6 +1131,7 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
             KdbpPrint("No threads in process 0x%08x!\n", ul);
          else
             KdbpPrint("No threads in current process!\n");
+         if (ReferencedProcess) ObDereferenceObject(Process);
          return TRUE;
       }
 
@@ -946,10 +1153,10 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
 
          if (Thread->Tcb.TrapFrame != NULL)
          {
-            if (Thread->Tcb.TrapFrame->PreviousMode == KernelMode)
+            if (Thread->Tcb.TrapFrame->PreviousPreviousMode == KernelMode)
                Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp;
             else
-               Esp = (PULONG)Thread->Tcb.TrapFrame->Esp;
+               Esp = (PULONG)Thread->Tcb.TrapFrame->HardwareEsp;
             Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
             Eip = Thread->Tcb.TrapFrame->Eip;
          }
@@ -979,6 +1186,9 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
          Entry = Entry->Flink;
       }
       while (Entry != &Process->ThreadListHead);
+
+      /* Release our reference, if any */
+      if (ReferencedProcess) ObDereferenceObject(Process);
    }
    else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
    {
@@ -1017,6 +1227,9 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
             KdbpPrint("thread: Invalid thread id!\n");
             return TRUE;
          }
+         
+         /* Remember our reference */
+         ReferencedThread = TRUE;
       }
 
       if (Thread->Tcb.State < (DeferredReady + 1))
@@ -1046,6 +1259,8 @@ KdbpCmdThread(ULONG Argc, PCHAR Argv[])
                 Thread->Tcb.TrapFrame,
                 NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState);
 
+        /* Release our reference if we had one */
+        if (ReferencedThread) ObDereferenceObject(Thread);
    }
 
    return TRUE;
@@ -1058,6 +1273,7 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
 {
    PLIST_ENTRY Entry;
    PEPROCESS Process;
+   BOOLEAN ReferencedProcess = FALSE;
    PCHAR State, pend, str1, str2;
    ULONG ul;
    extern LIST_ENTRY PsActiveProcessHead;
@@ -1065,7 +1281,7 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
    if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
    {
       Entry = PsActiveProcessHead.Flink;
-      if (Entry == &PsActiveProcessHead)
+      if (!Entry || Entry == &PsActiveProcessHead)
       {
          KdbpPrint("No processes in the system!\n");
          return TRUE;
@@ -1087,8 +1303,8 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
             str2 = "";
          }
 
-         State = ((Process->Pcb.State == PROCESS_STATE_TERMINATED) ? "Terminated" :
-                 ((Process->Pcb.State == PROCESS_STATE_ACTIVE) ? "Active" : "Unknown"));
+         State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
+                 ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
 
          KdbpPrint(" %s0x%08x  %-10s  %s%s\n",
                    str1,
@@ -1119,8 +1335,8 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
       {
          return TRUE;
       }
-      KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (UINT)ul,
-                (UINT)KdbCurrentThread->Cid.UniqueThread);
+      KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (ULONG)ul,
+                (ULONG)KdbCurrentThread->Cid.UniqueThread);
    }
    else
    {
@@ -1139,10 +1355,13 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
             KdbpPrint("proc: Invalid process id!\n");
             return TRUE;
          }
+         
+         /* Remember our reference */
+         ReferencedProcess = TRUE;
       }
 
-      State = ((Process->Pcb.State == PROCESS_STATE_TERMINATED) ? "Terminated" :
-              ((Process->Pcb.State == PROCESS_STATE_ACTIVE) ? "Active" : "Unknown"));
+      State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" :
+              ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition"));
       KdbpPrint("%s"
                 "  PID:             0x%08x\n"
                 "  State:           %s (0x%x)\n"
@@ -1151,6 +1370,9 @@ KdbpCmdProc(ULONG Argc, PCHAR Argv[])
                 Process->UniqueProcessId,
                 State, Process->Pcb.State,
                 Process->ImageFileName);
+
+        /* Release our reference, if any */
+        if (ReferencedProcess) ObDereferenceObject(Process);
    }
 
    return TRUE;
@@ -1194,8 +1416,10 @@ KdbpCmdMod(ULONG Argc, PCHAR Argv[])
    {
       if (!KdbpSymFindModuleByIndex(0, &Info))
       {
-         KdbpPrint("No modules.\n");
-         return TRUE;
+                 ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000;
+                 KdbpPrint("  Base      Size      Name\n");
+                 KdbpPrint("  %08x  %08x  %s\n", ntoskrnlBase, 0, "ntoskrnl.exe");
+                 return TRUE;
       }
       i = 1;
    }
@@ -1220,10 +1444,7 @@ KdbpCmdMod(ULONG Argc, PCHAR Argv[])
 STATIC BOOLEAN
 KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
 {
-   struct __attribute__((packed)) {
-      USHORT Limit;
-      ULONG Base;
-   } Reg;
+   KDESCRIPTOR Reg = {0};
    ULONG SegDesc[2];
    ULONG SegBase;
    ULONG SegLimit;
@@ -1236,7 +1457,7 @@ KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
    if (Argv[0][0] == 'i')
    {
       /* Read IDTR */
-      asm volatile("sidt %0" : : "m"(Reg));
+      Ke386GetInterruptDescriptorTable(*(PKDESCRIPTOR)&Reg.Limit);
 
       if (Reg.Limit < 7)
       {
@@ -1293,14 +1514,14 @@ KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
       if (Argv[0][0] == 'g')
       {
          /* Read GDTR */
-         asm volatile("sgdt %0" : : "m"(Reg));
+         Ke386GetGlobalDescriptorTable(*(PKDESCRIPTOR)&Reg.Limit);
          i = 8;
       }
       else
       {
          ASSERT(Argv[0][0] == 'l');
          /* Read LDTR */
-         asm volatile("sldt %0" : : "m"(Reg));
+         Ke386GetLocalDescriptorTable(Reg.Limit);
          i = 0;
          ul = 1 << 2;
       }
@@ -1424,7 +1645,7 @@ KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[])
 STATIC BOOLEAN
 KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
 {
-   PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
+   PKIPCR Pcr = (PKIPCR)KeGetPcr();
 
    KdbpPrint("Current PCR is at 0x%08x.\n", (INT)Pcr);
    KdbpPrint("  Tib.ExceptionList:         0x%08x\n"
@@ -1453,13 +1674,13 @@ KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
              "  VdmAlert:                  0x%08x\n"
              "  L2CacheSize:               0x%08x\n"
              "  InterruptMode:             0x%08x\n",
-             Pcr->Tib.ExceptionList, Pcr->Tib.StackBase, Pcr->Tib.StackLimit,
-             Pcr->Tib.SubSystemTib, Pcr->Tib.FiberData, Pcr->Tib.ArbitraryUserPointer,
-             Pcr->Tib.Self, Pcr->Self, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
+             Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit,
+             Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer,
+             Pcr->NtTib.Self, Pcr->Self, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
              Pcr->IDR, Pcr->KdVersionBlock, Pcr->IDT, Pcr->GDT, Pcr->TSS,
              Pcr->MajorVersion, Pcr->MinorVersion, Pcr->SetMember, Pcr->StallScaleFactor,
              Pcr->Number, Pcr->L2CacheAssociativity,
-             Pcr->VdmAlert, Pcr->L2CacheSize, Pcr->InterruptMode);
+             Pcr->VdmAlert, Pcr->SecondLevelCacheSize, Pcr->InterruptMode);
 
    return TRUE;
 }
@@ -1469,38 +1690,18 @@ KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
 STATIC BOOLEAN
 KdbpCmdTss(ULONG Argc, PCHAR Argv[])
 {
-   KTSS *Tss = KeGetCurrentKPCR()->TSS;
+   KTSS *Tss = KeGetPcr()->TSS;
 
    KdbpPrint("Current TSS is at 0x%08x.\n", (INT)Tss);
-   KdbpPrint("  PreviousTask:  0x%08x\n"
-             "  Ss0:Esp0:      0x%04x:0x%08x\n"
-             "  Ss1:Esp1:      0x%04x:0x%08x\n"
-             "  Ss2:Esp2:      0x%04x:0x%08x\n"
-             "  Cr3:           0x%08x\n"
-             "  Eip:           0x%08x\n"
-             "  Eflags:        0x%08x\n"
-             "  Eax:           0x%08x\n"
-             "  Ecx:           0x%08x\n"
-             "  Edx:           0x%08x\n"
-             "  Ebx:           0x%08x\n"
-             "  Esp:           0x%08x\n"
-             "  Ebp:           0x%08x\n"
-             "  Esi:           0x%08x\n"
-             "  Edi:           0x%08x\n"
+   KdbpPrint("  Eip:           0x%08x\n"
              "  Es:            0x%04x\n"
              "  Cs:            0x%04x\n"
              "  Ss:            0x%04x\n"
              "  Ds:            0x%04x\n"
              "  Fs:            0x%04x\n"
              "  Gs:            0x%04x\n"
-             "  Ldt:           0x%04x\n"
-             "  Trap:          0x%04x\n"
              "  IoMapBase:     0x%04x\n",
-             Tss->PreviousTask, Tss->Ss0, Tss->Esp0, Tss->Ss1, Tss->Esp1,
-             Tss->Ss2, Tss->Esp2, Tss->Cr3, Tss->Eip, Tss->Eflags, Tss->Eax,
-             Tss->Ecx, Tss->Edx, Tss->Ebx, Tss->Esp, Tss->Ebp, Tss->Esi,
-             Tss->Edi, Tss->Es, Tss->Cs, Tss->Ss, Tss->Ds, Tss->Fs, Tss->Gs,
-             Tss->Ldt, Tss->Trap, Tss->IoMapBase);
+             Tss->Eip, Tss->Es, Tss->Cs, Tss->Ds, Tss->Fs, Tss->Gs, Tss->IoMapBase);
    return TRUE;
 }
 
@@ -1509,8 +1710,9 @@ KdbpCmdTss(ULONG Argc, PCHAR Argv[])
 STATIC BOOLEAN
 KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[])
 {
-   KEBUGCHECK(0xDEADDEAD);
-   return TRUE;
+   /* Set the flag and quit looping */
+   KdbpBugCheckRequested = TRUE;
+   return FALSE;
 }
 
 /*!\brief Sets or displays a config variables value.
@@ -1534,6 +1736,7 @@ KdbpCmdSet(ULONG Argc, PCHAR Argv[])
       KdbpPrint("Available settings:\n");
       KdbpPrint("  syntax [intel|at&t]\n");
       KdbpPrint("  condition [exception|*] [first|last] [never|always|kmode|umode]\n");
+      KdbpPrint("  break_on_module_load [true|false]\n");
    }
    else if (strcmp(Argv[1], "syntax") == 0)
    {
@@ -1577,7 +1780,7 @@ KdbpCmdSet(ULONG Argc, PCHAR Argv[])
             l = -1;
          else
          {
-            l = (LONG)strtoul(Argv[2], &pend, 0);
+            l = strtoul(Argv[2], &pend, 0);
             if (Argv[2] == pend)
             {
                for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
@@ -1648,6 +1851,22 @@ KdbpCmdSet(ULONG Argc, PCHAR Argv[])
          }
       }
    }
+   else if (strcmp(Argv[1], "break_on_module_load") == 0)
+   {
+      if (Argc == 2)
+         KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled");
+      else if (Argc >= 3)
+      {
+         if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 ||
+             _stricmp(Argv[2], "true") == 0)
+            KdbBreakOnModuleLoad = TRUE;
+         else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 ||
+                  _stricmp(Argv[2], "false") == 0)
+            KdbBreakOnModuleLoad = FALSE;
+         else
+            KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
+      }
+   }
    else
       KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
 
@@ -1699,9 +1918,9 @@ KdbpPrint(
    STATIC BOOLEAN TerminalReportsSize = TRUE;
    CHAR c = '\0';
    PCHAR p, p2;
-   INT Length;
-   INT i, j;
-   INT RowsPrintedByTerminal;
+   ULONG Length;
+   ULONG i, j;
+   LONG RowsPrintedByTerminal;
    ULONG ScanCode;
    va_list ap;
 
@@ -1720,6 +1939,8 @@ KdbpPrint(
 
       TerminalInitialized = TRUE;
       Length = 0;
+         KeStallExecutionProcessor(100000);
+
       for (;;)
       {
          c = KdbpTryGetCharSerial(5000);
@@ -1738,10 +1959,11 @@ KdbpPrint(
    if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
        (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
    {
-      if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalReportsSize)
+      if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
       {
          /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
          TerminalReportsSize = FALSE;
+                KeStallExecutionProcessor(100000);
          DbgPrint("\x1b[18t");
          c = KdbpTryGetCharSerial(5000);
          if (c == KEY_ESC)
@@ -1773,6 +1995,8 @@ KdbpPrint(
                   }
                }
             }
+                       /* Clear further characters */
+                       while ((c = KdbpTryGetCharSerial(5000)) != -1);
          }
       }
 
@@ -1812,7 +2036,8 @@ KdbpPrint(
       /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
 
       /* Display a prompt if we printed one screen full of text */
-      if ((KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
+      if (KdbNumberOfRowsTerminal > 0 &&
+          (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
       {
          if (KdbNumberOfColsPrinted > 0)
             DbgPrint("\n");
@@ -1863,10 +2088,14 @@ KdbpPrint(
                while (!isalpha(p2[j++]));
                strcpy(p2, p2 + j);
             }
+            else
+            {
+                strcpy(p2, p2 + 1);
+            }
          }
       }
 
-      DbgPrint("%s", p);
+         DbgPrint("%s", p);
 
       if (c != '\0')
          p[i + 1] = c;
@@ -1897,8 +2126,8 @@ STATIC VOID
 KdbpCommandHistoryAppend(
    IN PCHAR Command)
 {
-   LONG Length1 = strlen(Command) + 1;
-   LONG Length2 = 0;
+   ULONG Length1 = strlen(Command) + 1;
+   ULONG Length2 = 0;
    INT i;
    PCHAR Buffer;
 
@@ -1914,7 +2143,7 @@ KdbpCommandHistoryAppend(
    /* Calculate Length1 and Length2 */
    Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex;
    KdbCommandHistoryBufferIndex += Length1;
-   if (KdbCommandHistoryBufferIndex >= RTL_NUMBER_OF(KdbCommandHistoryBuffer))
+   if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer))
    {
       KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer);
       Length2 = KdbCommandHistoryBufferIndex;
@@ -2017,7 +2246,7 @@ KdbpReadCommand(
          NextKey = '\0';
       }
 
-      if ((Buffer - Orig) >= (Size - 1))
+      if ((ULONG)(Buffer - Orig) >= (Size - 1))
       {
          /* Buffer is full, accept only newlines */
          if (Key != '\n')
@@ -2029,13 +2258,14 @@ KdbpReadCommand(
          /* Read the next char - this is to throw away a \n which most clients should
           * send after \r.
           */
+                KeStallExecutionProcessor(100000);
          if (KdbDebugState & KD_DEBUG_KDSERIAL)
             NextKey = KdbpTryGetCharSerial(5);
          else
             NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
          if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
             NextKey = '\0';
-         DbgPrint("\n");
+         KdbpPrint("\n");
         /*
          * Repeat the last command if the user presses enter. Reduces the
          * risk of RSI when single-stepping.
@@ -2060,9 +2290,9 @@ KdbpReadCommand(
             Buffer--;
             *Buffer = 0;
             if (EchoOn)
-               DbgPrint("%c %c", KEY_BS, KEY_BS);
+               KdbpPrint("%c %c", KEY_BS, KEY_BS);
            else
-               DbgPrint(" %c", KEY_BS);
+               KdbpPrint(" %c", KEY_BS);
          }
       }
       else if (ScanCode == KEY_SCAN_UP)
@@ -2087,15 +2317,15 @@ KdbpReadCommand(
                Buffer--;
                *Buffer = 0;
                if (EchoOn)
-                  DbgPrint("%c %c", KEY_BS, KEY_BS);
+                  KdbpPrint("%c %c", KEY_BS, KEY_BS);
                else
-                  DbgPrint(" %c", KEY_BS);
+                  KdbpPrint(" %c", KEY_BS);
             }
             i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
             memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
             Orig[i] = '\0';
             Buffer = Orig + i;
-            DbgPrint("%s", Orig);
+            KdbpPrint("%s", Orig);
          }
       }
       else if (ScanCode == KEY_SCAN_DOWN)
@@ -2103,7 +2333,7 @@ KdbpReadCommand(
          if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
          {
             i = CmdHistIndex + 1;
-            if (i >= RTL_NUMBER_OF(KdbCommandHistory))
+            if (i >= (INT)RTL_NUMBER_OF(KdbCommandHistory))
                i = 0;
             if (KdbCommandHistory[i] != NULL)
             {
@@ -2113,22 +2343,22 @@ KdbpReadCommand(
                   Buffer--;
                   *Buffer = 0;
                   if (EchoOn)
-                     DbgPrint("%c %c", KEY_BS, KEY_BS);
+                     KdbpPrint("%c %c", KEY_BS, KEY_BS);
                   else
-                     DbgPrint(" %c", KEY_BS);
+                     KdbpPrint(" %c", KEY_BS);
                }
                i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1);
                memcpy(Orig, KdbCommandHistory[CmdHistIndex], i);
                Orig[i] = '\0';
                Buffer = Orig + i;
-               DbgPrint("%s", Orig);
+               KdbpPrint("%s", Orig);
             }
          }
       }
       else
       {
          if (EchoOn)
-            DbgPrint("%c", Key);
+            KdbpPrint("%c", Key);
 
          *Buffer = Key;
          Buffer++;
@@ -2143,7 +2373,7 @@ KdbpReadCommand(
  * \retval TRUE   Don't continue execution.
  * \retval FALSE  Continue execution (leave KDB)
  */
-STATIC BOOL
+STATIC BOOLEAN
 KdbpDoCommand(
    IN PCHAR Command)
 {
@@ -2206,14 +2436,14 @@ KdbpCliMainLoop(
    {
       if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip))
       {
-         DbgPrint("<%x>", KdbCurrentTrapFrame->Tf.Eip);
+         KdbpPrint("<%x>", KdbCurrentTrapFrame->Tf.Eip);
       }
-      DbgPrint(": ");
+      KdbpPrint(": ");
       if (KdbpDisassemble(KdbCurrentTrapFrame->Tf.Eip, KdbUseIntelSyntax) < 0)
       {
-         DbgPrint("<INVALID>");
+         KdbpPrint("<INVALID>");
       }
-      DbgPrint("\n");
+      KdbpPrint("\n");
    }
 
    /* Flush the input buffer */
@@ -2231,7 +2461,7 @@ KdbpCliMainLoop(
    do
    {
       /* Print the prompt */
-      DbgPrint("kdb:> ");
+      KdbpPrint("kdb:> ");
 
       /* Read a command and remember it */
       KdbpReadCommand(Command, sizeof (Command));
@@ -2253,9 +2483,10 @@ KdbpCliMainLoop(
 VOID
 KdbpCliModuleLoaded(IN PUNICODE_STRING Name)
 {
-   return;
+   if (!KdbBreakOnModuleLoad)
+      return;
 
-   DbgPrint("Module %wZ loaded.\n", Name);
+   KdbpPrint("Module %wZ loaded.\n", Name);
    DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
 }
 
@@ -2322,7 +2553,7 @@ KdbpCliInit()
    HANDLE hFile = NULL;
    INT FileSize;
    PCHAR FileBuffer;
-   ULONG OldEflags;
+   ULONG OldEflags = 0;
 
    /* Initialize the object attributes */
    RtlInitUnicodeString(&FileName, L"\\SystemRoot\\system32\\drivers\\etc\\KDBinit");
@@ -2367,12 +2598,12 @@ KdbpCliInit()
       DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
       return;
    }
-   FileSize = min(FileSize, Iosb.Information);
+   FileSize = min(FileSize, (INT)Iosb.Information);
    FileBuffer[FileSize] = '\0';
 
    /* Enter critical section */
    Ke386SaveFlags(OldEflags);
-   Ke386DisableInterrupts();
+   _disable();
 
    /* Interpret the init file... */
    KdbInitFileBuffer = FileBuffer;