Merge trunk head (r43756)
[reactos.git] / reactos / ntoskrnl / ke / bug.c
index 2c3bcea..f9cc43e 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 #if defined (ALLOC_PRAGMA)
 #pragma alloc_text(INIT, KiInitializeBugCheck)
@@ -29,8 +29,77 @@ ULONG KiHardwareTrigger;
 PUNICODE_STRING KiBugCheckDriver;
 ULONG_PTR KiBugCheckData[5];
 
+/* Bugzilla Reporting */
+UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion;
+UNICODE_STRING KeRosVideoBiosDate, KeRosVideoBiosVersion;
+
 /* PRIVATE FUNCTIONS *********************************************************/
 
+PVOID
+NTAPI
+KiPcToFileHeader(IN PVOID Pc,
+                 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
+                 IN BOOLEAN DriversOnly,
+                 OUT PBOOLEAN InKernel)
+{
+    ULONG i = 0;
+    PVOID ImageBase, PcBase = NULL;
+    PLDR_DATA_TABLE_ENTRY Entry;
+    PLIST_ENTRY ListHead, NextEntry;
+
+    /* Check which list we should use */
+    ListHead = (KeLoaderBlock) ? &KeLoaderBlock->LoadOrderListHead :
+                                 &PsLoadedModuleList;
+
+    /* Assume no */
+    *InKernel = FALSE;
+
+    /* Set list pointers and make sure it's valid */
+    NextEntry = ListHead->Flink;
+    if (NextEntry)
+    {
+        /* Start loop */
+        while (NextEntry != ListHead)
+        {
+            /* Increase entry */
+            i++;
+
+            /* Check if this is a kernel entry and we only want drivers */
+            if ((i <= 2) && (DriversOnly == TRUE))
+            {
+                /* Skip it */
+                NextEntry = NextEntry->Flink;
+                continue;
+            }
+
+            /* Get the loader entry */
+            Entry = CONTAINING_RECORD(NextEntry,
+                                      LDR_DATA_TABLE_ENTRY,
+                                      InLoadOrderLinks);
+
+            /* Move to the next entry */
+            NextEntry = NextEntry->Flink;
+            ImageBase = Entry->DllBase;
+
+            /* Check if this is the right one */
+            if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+                ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+            {
+                /* Return this entry */
+                *LdrEntry = Entry;
+                PcBase = ImageBase;
+
+                /* Check if this was a kernel or HAL entry */
+                if (i <= 2) *InKernel = TRUE;
+                break;
+            }
+        }
+    }
+
+    /* Return the base address */
+    return PcBase;
+}
+
 BOOLEAN
 NTAPI
 KiRosPrintAddress(PVOID address)
@@ -67,46 +136,256 @@ KiRosPrintAddress(PVOID address)
     return(FALSE);
 }
 
-VOID
+PVOID
 NTAPI
-KeRosDumpStackFrames(IN PULONG Frame OPTIONAL,
-                     IN ULONG FrameCount OPTIONAL)
+KiRosPcToUserFileHeader(IN PVOID Pc,
+                        OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
 {
-    ULONG Frames[32];
-    ULONG i, Addr;
+    PVOID ImageBase, PcBase = NULL;
+    PLDR_DATA_TABLE_ENTRY Entry;
+    PLIST_ENTRY ListHead, NextEntry;
 
-    /* If the caller didn't ask, assume 32 frames */
-    if (!FrameCount) FrameCount = 32;
+    /*
+     * We know this is valid because we should only be called after a
+     * succesfull address from RtlWalkFrameChain for UserMode, which
+     * validates everything for us.
+     */
+    ListHead = &KeGetCurrentThread()->
+               Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList;
 
-    /* Get the current frames */
-    FrameCount = RtlCaptureStackBackTrace(2, FrameCount, (PVOID*)Frames, NULL);
+    /* Set list pointers and make sure it's valid */
+    NextEntry = ListHead->Flink;
+    if (NextEntry)
+    {
+        /* Start loop */
+        while (NextEntry != ListHead)
+        {
+            /* Get the loader entry */
+            Entry = CONTAINING_RECORD(NextEntry,
+                                      LDR_DATA_TABLE_ENTRY,
+                                      InLoadOrderLinks);
+
+            /* Move to the next entry */
+            NextEntry = NextEntry->Flink;
+            ImageBase = Entry->DllBase;
+
+            /* Check if this is the right one */
+            if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+                ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+            {
+                /* Return this entry */
+                *LdrEntry = Entry;
+                PcBase = ImageBase;
+                break;
+            }
+        }
+    }
+
+    /* Return the base address */
+    return PcBase;
+}
+
+USHORT
+NTAPI
+KeRosCaptureUserStackBackTrace(IN ULONG FramesToSkip,
+                               IN ULONG FramesToCapture,
+                               OUT PVOID *BackTrace,
+                               OUT PULONG BackTraceHash OPTIONAL)
+{
+    PVOID Frames[2 * 64];
+    ULONG FrameCount;
+    ULONG Hash = 0, i;
+
+    /* Skip a frame for the caller */
+    FramesToSkip++;
+
+    /* Don't go past the limit */
+    if ((FramesToCapture + FramesToSkip) >= 128) return 0;
+
+    /* Do the back trace */
+    FrameCount = RtlWalkFrameChain(Frames, FramesToCapture + FramesToSkip, 1);
+
+    /* Make sure we're not skipping all of them */
+    if (FrameCount <= FramesToSkip) return 0;
+
+    /* Loop all the frames */
+    for (i = 0; i < FramesToCapture; i++)
+    {
+        /* Don't go past the limit */
+        if ((FramesToSkip + i) >= FrameCount) break;
+
+        /* Save this entry and hash it */
+        BackTrace[i] = Frames[FramesToSkip + i];
+        Hash += PtrToUlong(BackTrace[i]);
+    }
+
+    /* Write the hash */
+    if (BackTraceHash) *BackTraceHash = Hash;
+
+    /* Clear the other entries and return count */
+    RtlFillMemoryUlong(Frames, 128, 0);
+    return (USHORT)i;
+}
+
+VOID
+FASTCALL
+KeRosDumpStackFrameArray(IN PULONG_PTR Frames,
+                         IN ULONG FrameCount)
+{
+    ULONG i;
+    ULONG_PTR Addr;
+    BOOLEAN InSystem;
+    PVOID p;
 
-    /* Now loop them (skip the two. One for the dumper, one for the caller) */
+    /* GCC complaints that it may be used uninitialized */
+    PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
+
+    /* Loop them */
     for (i = 0; i < FrameCount; i++)
     {
         /* Get the EIP */
         Addr = Frames[i];
+        if (!Addr)
+        {
+               break;
+        }
 
-        /* If we had a custom frame, make sure we've reached it first */
-        if ((Frame) && (Frame[1] == Addr))
+        /* Get the base for this file */
+        if (Addr > (ULONG_PTR)MmHighestUserAddress)
         {
-            Frame = NULL;
+            /* We are in kernel */
+            p = KiPcToFileHeader((PVOID)Addr, &LdrEntry, FALSE, &InSystem);
         }
-        else if (Frame)
+        else
         {
-            /* Skip this entry */
-            continue;
+            /* We are in user land */
+            p = KiRosPcToUserFileHeader((PVOID)Addr, &LdrEntry);
+        }
+        if (p)
+        {
+#ifdef KDBG
+            if (!KdbSymPrintAddress((PVOID)Addr))
+#endif
+            {
+                /* Print out the module name */
+                Addr -= (ULONG_PTR)LdrEntry->DllBase;
+                DbgPrint("<%wZ: %p>", &LdrEntry->FullDllName, (PVOID)Addr);
+            }
+        }
+        else
+        {
+            /* Print only the address */
+            DbgPrint("<%p>", (PVOID)Addr);
         }
-
-        /* Print it out */
-        if (!KiRosPrintAddress((PVOID)Addr)) DbgPrint("<%X>", Addr);
 
         /* Go to the next frame */
         DbgPrint("\n");
     }
+}
+
+VOID
+NTAPI
+KeRosDumpStackFrames(IN PULONG_PTR Frame OPTIONAL,
+                     IN ULONG FrameCount OPTIONAL)
+{
+    ULONG_PTR Frames[32];
+    ULONG RealFrameCount;
+
+    /* If the caller didn't ask, assume 32 frames */
+    if (!FrameCount || FrameCount > 32) FrameCount = 32;
+
+    if (Frame)
+    {
+        /* Dump them */
+        KeRosDumpStackFrameArray(Frame, FrameCount);
+    }
+    else
+    {
+        /* Get the current frames (skip the two. One for the dumper, one for the caller) */
+        RealFrameCount = RtlCaptureStackBackTrace(2, FrameCount, (PVOID*)Frames, NULL);
 
-    /* Finish the output */
-    DbgPrint("\n");
+        /* Dump them */
+        KeRosDumpStackFrameArray(Frames, RealFrameCount);
+
+        /* Count left for user mode? */
+        if (FrameCount - RealFrameCount > 0)
+        {
+            /* Get the current frames */
+            RealFrameCount = KeRosCaptureUserStackBackTrace(-1, FrameCount - RealFrameCount, (PVOID*)Frames, NULL);
+
+            /* Dump them */
+            KeRosDumpStackFrameArray(Frames, RealFrameCount);
+        }
+    }
+}
+
+
+VOID
+NTAPI
+KeRosDumpTriageForBugZillaReport(VOID)
+{
+#if 0
+    extern BOOLEAN KiFastSystemCallDisable, KiSMTProcessorsPresent;
+    extern ULONG KeI386MachineType, MxcsrFeatureMask;
+    extern BOOLEAN Ke386Pae, Ke386NoExecute;
+
+    DbgPrint("ReactOS has crashed! Please go to http://www.reactos.org/bugzilla/enter_bug.cgi to file a bug!\n");
+    DbgPrint("\nHardware Information\n");
+    DbgPrint("Processor Architecture: %d\n"
+             "Feature Bits: %d\n"
+             "System Call Disabled: %d\n"
+             "NPX Present: %d\n"
+             "MXCsr Mask: %d\n"
+             "MXCsr Feature Mask: %d\n"
+             "XMMI Present: %d\n"
+             "FXSR Present: %d\n"
+             "Machine Type: %d\n"
+             "PAE: %d\n"
+             "NX: %d\n"
+             "Processors: %d\n"
+             "Active Processors: %d\n"
+             "Pentium LOCK Bug: %d\n"
+             "Hyperthreading: %d\n"
+             "CPU Manufacturer: %s\n"
+             "CPU Name: %wZ\n"
+             "CPUID: %d\n"
+             "CPU Type: %d\n"
+             "CPU Stepping: %d\n"
+             "CPU Speed: %d\n"
+             "CPU L2 Cache: %d\n"
+             "BIOS Date: %wZ\n"
+             "BIOS Version: %wZ\n"
+             "Video BIOS Date: %wZ\n"
+             "Video BIOS Version: %wZ\n"
+             "Memory: %d\n",
+             KeProcessorArchitecture,
+             KeFeatureBits,
+             KiFastSystemCallDisable,
+             KeI386NpxPresent,
+             KiMXCsrMask,
+             MxcsrFeatureMask,
+             KeI386XMMIPresent,
+             KeI386FxsrPresent,
+             KeI386MachineType,
+             Ke386Pae,
+             Ke386NoExecute,
+             KeNumberProcessors,
+             KeActiveProcessors,
+             KiI386PentiumLockErrataPresent,
+             KiSMTProcessorsPresent,
+             KeGetCurrentPrcb()->VendorString,
+             &KeRosProcessorName,
+             KeGetCurrentPrcb()->CpuID,
+             KeGetCurrentPrcb()->CpuType,
+             KeGetCurrentPrcb()->CpuStep,
+             KeGetCurrentPrcb()->MHz,
+             ((PKIPCR)KeGetPcr())->SecondLevelCacheSize,
+             &KeRosBiosDate,
+             &KeRosBiosVersion,
+             &KeRosVideoBiosDate,
+             &KeRosVideoBiosVersion,
+             MmNumberOfPhysicalPages * PAGE_SIZE);
+#endif
 }
 
 VOID
@@ -148,7 +427,7 @@ KiInitializeBugCheck(VOID)
     }
 }
 
-VOID
+BOOLEAN
 NTAPI
 KeGetBugMessageText(IN ULONG BugCheckCode,
                     OUT PANSI_STRING OutputString OPTIONAL)
@@ -157,6 +436,10 @@ KeGetBugMessageText(IN ULONG BugCheckCode,
     ULONG IdOffset;
     ULONG_PTR MessageEntry;
     PCHAR BugCode;
+    BOOLEAN Result = FALSE;
+
+    /* Make sure we're not bugchecking too early */
+    if (!KiBugCodeMessages) return Result;
 
     /* Find the message. This code is based on RtlFindMesssage */
     for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++)
@@ -164,7 +447,7 @@ KeGetBugMessageText(IN ULONG BugCheckCode,
         /* Check if the ID Matches */
         if ((BugCheckCode >= KiBugCodeMessages->Blocks[i].LowId) &&
             (BugCheckCode <= KiBugCodeMessages->Blocks[i].HighId))
-            {
+        {
             /* Get Offset to Entry */
             MessageEntry = KiBugCodeMessages->Blocks[i].OffsetToEntries +
                            (ULONG_PTR)KiBugCodeMessages;
@@ -182,22 +465,39 @@ KeGetBugMessageText(IN ULONG BugCheckCode,
             BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
             i = strlen(BugCode);
 
-            /* Return it in the OutputString */
+            /* Handle newlines */
+            while ((i > 0) && ((BugCode[i] == '\n') ||
+                               (BugCode[i] == '\r') ||
+                               (BugCode[i] == ANSI_NULL)))
+            {
+                /* Check if we have a string to return */
+                if (!OutputString) BugCode[i] = ANSI_NULL;
+                i--;
+            }
+
+            /* Check if caller wants an output string */
             if (OutputString)
             {
+                /* Return it in the OutputString */
                 OutputString->Buffer = BugCode;
-                OutputString->Length = i + 1;
-                OutputString->MaximumLength = i + 1;
+                OutputString->Length = (USHORT)i + 1;
+                OutputString->MaximumLength = (USHORT)i + 1;
             }
             else
             {
                 /* Direct Output to Screen */
                 InbvDisplayString(BugCode);
                 InbvDisplayString("\r");
-                break;
             }
+
+            /* We're done */
+            Result = TRUE;
+            break;
         }
     }
+
+    /* Return the result */
+    return Result;
 }
 
 VOID
@@ -251,72 +551,25 @@ VOID
 NTAPI
 KiBugCheckDebugBreak(IN ULONG StatusCode)
 {
-    /* If KDBG isn't connected, freeze the CPU, otherwise, break */
-    if (KdDebuggerNotPresent) for (;;) Ke386HaltProcessor();
-    DbgBreakPointWithStatus(StatusCode);
-}
-
-PVOID
-NTAPI
-KiPcToFileHeader(IN PVOID Eip,
-                 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
-                 IN BOOLEAN DriversOnly,
-                 OUT PBOOLEAN InKernel)
-{
-    ULONG i = 0;
-    PVOID ImageBase, EipBase = NULL;
-    PLDR_DATA_TABLE_ENTRY Entry;
-    PLIST_ENTRY ListHead, NextEntry;
-    extern LIST_ENTRY PsLoadedModuleList;
-
-    /* Assume no */
-    *InKernel = FALSE;
-
-    /* Set list pointers and make sure it's valid */
-    ListHead = &PsLoadedModuleList;
-    NextEntry = ListHead->Flink;
-    if (NextEntry)
+    /*
+     * Wrap this in SEH so we don't crash if
+     * there is no debugger or if it disconnected
+     */
+DoBreak:
+    _SEH2_TRY
     {
-        /* Start loop */
-        while (NextEntry != ListHead)
-        {
-            /* Increase entry */
-            i++;
-
-            /* Check if this is a kernel entry and we only want drivers */
-            if ((i <= 2) && (DriversOnly == TRUE))
-            {
-                /* Skip it */
-                NextEntry = NextEntry->Flink;
-                continue;
-            }
-
-            /* Get the loader entry */
-            Entry = CONTAINING_RECORD(NextEntry,
-                                      LDR_DATA_TABLE_ENTRY,
-                                      InLoadOrderLinks);
-
-            /* Move to the next entry */
-            NextEntry = NextEntry->Flink;
-            ImageBase = Entry->DllBase;
-
-            /* Check if this is the right one */
-            if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) &&
-                ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
-            {
-                /* Return this entry */
-                *LdrEntry = Entry;
-                EipBase = ImageBase;
-
-                /* Check if this was a kernel or HAL entry */
-                if (i <= 2) *InKernel = TRUE;
-                break;
-            }
-        }
+        /* Breakpoint */
+        DbgBreakPointWithStatus(StatusCode);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* No debugger, halt the CPU */
+        HalHaltSystem();
     }
+    _SEH2_END;
 
-    /* Return the base address */
-    return EipBase;
+    /* Break again if this wasn't first try */
+    if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak;
 }
 
 PCHAR
@@ -370,13 +623,9 @@ KiDumpParameterImages(IN PCHAR Message,
                                      &InSystem);
         if (!ImageBase)
         {
-            /* Driver wasn't found, check for unloaded driver */
-            DriverName = NULL; // FIXME: ROS can't
-            if (!DriverName) continue;
-
-            /* Convert the driver name */
-            ImageBase = (PVOID)Parameters[i];
-            ConversionRoutine(DriverName, AnsiName, sizeof(AnsiName));
+            /* FIXME: Add code to check for unloaded drivers */
+            DPRINT1("Potentially unloaded driver!\n");
+            continue;
         }
         else
         {
@@ -489,10 +738,10 @@ KiDisplayBlueScreen(IN ULONG MessageId,
     /* Print message for technical information */
     KeGetBugMessageText(BUGCHECK_TECH_INFO, NULL);
 
-    /* Show the techincal Data */
+    /* Show the technical Data */
     sprintf(AnsiName,
-            "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
-            KiBugCheckData[0],
+            "\r\n\r\n*** STOP: 0x%p (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
+            (PVOID)KiBugCheckData[0],
             (PVOID)KiBugCheckData[1],
             (PVOID)KiBugCheckData[2],
             (PVOID)KiBugCheckData[3],
@@ -530,7 +779,7 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
     CHAR AnsiName[128];
     BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE;
     PCHAR HardErrCaption = NULL, HardErrMessage = NULL;
-    PVOID Eip = NULL, Memory;
+    PVOID Pc = NULL, Memory;
     PVOID DriverBase;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
     PULONG_PTR HardErrorParameters;
@@ -640,12 +889,12 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
                 if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
             }
 
-            /* Check if we got one now and if we need to get EIP */
+            /* Check if we got one now and if we need to get the Program Counter */
             if ((TrapFrame) &&
                 (BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED))
             {
-                /* Get EIP */
-                Eip = (PVOID)TrapFrame->Eip;
+                /* Get the Program Counter */
+                Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
             }
             break;
 
@@ -659,11 +908,14 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
              * and provide a more detailed analysis. For now, we don't.
              */
 
-            /* Eip is in parameter 4 */
-            Eip = (PVOID)BugCheckParameter4;
+            /* Program Counter is in parameter 4 */
+            Pc = (PVOID)BugCheckParameter4;
 
             /* Get the driver base */
-            DriverBase = KiPcToFileHeader(Eip, &LdrEntry, FALSE, &IsSystem);
+            DriverBase = KiPcToFileHeader(Pc,
+                                          &LdrEntry,
+                                          FALSE,
+                                          &IsSystem);
             if (IsSystem)
             {
                 /*
@@ -703,8 +955,8 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
                 KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
             }
 
-            /* Clear EIP so we don't look it up later */
-            Eip = NULL;
+            /* Clear Pc so we don't look it up later */
+            Pc = NULL;
             break;
 
         /* Hard error */
@@ -740,12 +992,12 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
             /* Check if we have a frame now */
             if (TrapFrame)
             {
-                /* Get EIP */
-                Eip = (PVOID)TrapFrame->Eip;
-                KiBugCheckData[3] = (ULONG)Eip;
+                /* Get the Program Counter */
+                Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
+                KiBugCheckData[3] = (ULONG_PTR)Pc;
 
                 /* Find out if was in the kernel or drivers */
-                DriverBase = KiPcToFileHeader(Eip,
+                DriverBase = KiPcToFileHeader(Pc,
                                               &LdrEntry,
                                               FALSE,
                                               &IsSystem);
@@ -775,8 +1027,8 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
         /* Check if the driver forgot to unlock pages */
         case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
 
-            /* EIP is in parameter 1 */
-            Eip = (PVOID)BugCheckParameter1;
+            /* Program Counter is in parameter 1 */
+            Pc = (PVOID)BugCheckParameter1;
             break;
 
         /* Check if the driver consumed too many PTEs */
@@ -807,19 +1059,21 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
     }
     else
     {
-        /* Do we have an EIP? */
-        if (Eip)
+        /* Do we have a Program Counter? */
+        if (Pc)
         {
             /* Dump image name */
             KiDumpParameterImages(AnsiName,
-                                  (PULONG_PTR)&Eip,
+                                  (PULONG_PTR)&Pc,
                                   1,
                                   KeBugCheckUnicodeToAnsi);
         }
     }
 
     /* Check if we need to save the context for KD */
-    if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG)&Context;
+#ifdef _WINKD_
+    if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG_PTR)&Context;
+#endif
 
     /* Check if a debugger is connected */
     if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled))
@@ -854,18 +1108,24 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
             /* Break in the debugger */
             KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST);
         }
+        else
+        {
+            /*
+             * ROS HACK.
+             * Ok, so debugging is enabled, but KDBG isn't there.
+             * We'll manually dump the stack for the user.
+             */
+            KeRosDumpStackFrames(NULL, 0);
+
+            /* ROS HACK 2: Generate something useful for Bugzilla */
+            KeRosDumpTriageForBugZillaReport();
+        }
     }
 
     /* Raise IRQL to HIGH_LEVEL */
     _disable();
     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
 
-    /* ROS HACK: Unlock the Kernel Address Space if we own it */
-    if (KernelAddressSpaceLock.Owner == KeGetCurrentThread())
-    {
-        MmUnlockAddressSpace(MmGetKernelAddressSpace());
-    }
-
     /* Avoid recursion */
     if (!InterlockedDecrement((PLONG)&KeBugCheckCount))
     {
@@ -879,7 +1139,7 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
             if (i != (LONG)KeGetCurrentProcessorNumber())
             {
                 /* Send the IPI and give them one second to catch up */
-                KiIpiSendRequest(1 << i, IPI_FREEZE);
+                KiIpiSend(1 << i, IPI_FREEZE);
                 KeStallExecutionProcessor(1000000);
             }
         }
@@ -896,7 +1156,9 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
         if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
         {
             /* Enable it */
+#ifdef _WINKD_
             KdEnableDebuggerWithLock(FALSE);
+#endif
         }
         else
         {
@@ -909,13 +1171,7 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
 
         /* FIXME: Support Triage Dump */
 
-        /* Write the crash dump */
-        MmDumpToPagingFile(KiBugCheckData[4],
-                           KiBugCheckData[0],
-                           KiBugCheckData[1],
-                           KiBugCheckData[2],
-                           KiBugCheckData[3],
-                           TrapFrame);
+        /* FIXME: Write the crash dump */
     }
     else
     {
@@ -928,8 +1184,8 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
         }
         else if (KeBugCheckOwnerRecursionCount > 2)
         {
-            /* Halt the CPU */
-            for (;;) Ke386HaltProcessor();
+            /* Halt execution */
+            while (TRUE);
         }
     }
 
@@ -942,16 +1198,34 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
     if (Reboot)
     {
         /* Unload symbols */
-        DbgUnLoadImageSymbols(NULL, NtCurrentProcess(), 0);
+        DbgUnLoadImageSymbols(NULL, (PVOID)MAXULONG_PTR, 0);
         HalReturnToFirmware(HalRebootRoutine);
     }
 
     /* Attempt to break in the debugger (otherwise halt CPU) */
     KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
+
+    /* Shouldn't get here */
+    while (TRUE);
 }
 
 /* PUBLIC FUNCTIONS **********************************************************/
 
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+KeInitializeCrashDumpHeader(IN ULONG Type,
+                            IN ULONG Flags,
+                            OUT PVOID Buffer,
+                            IN ULONG BufferSize,
+                            OUT ULONG BufferNeeded OPTIONAL)
+{
+    UNIMPLEMENTED;
+    return STATUS_UNSUCCESSFUL;
+}
+
 /*
  * @implemented
  */
@@ -1007,6 +1281,17 @@ KeDeregisterBugCheckReasonCallback(
     return Status;
 }
 
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+KeDeregisterNmiCallback(PVOID Handle)
+{
+    UNIMPLEMENTED;
+    return STATUS_UNSUCCESSFUL;
+}
+
 /*
  * @implemented
  */
@@ -1077,6 +1362,18 @@ KeRegisterBugCheckReasonCallback(
     return Status;
 }
 
+/*
+ * @unimplemented
+ */
+PVOID
+NTAPI
+KeRegisterNmiCallback(IN PNMI_CALLBACK CallbackRoutine,
+                      IN PVOID Context)
+{
+    UNIMPLEMENTED;
+    return NULL;
+}
+
 /*
  * @implemented
  */
@@ -1108,4 +1405,30 @@ KeBugCheck(ULONG BugCheckCode)
     KeBugCheckWithTf(BugCheckCode, 0, 0, 0, 0, NULL);
 }
 
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeEnterKernelDebugger(VOID)
+{
+    /* Disable interrupts */
+    KiHardwareTrigger = 1;
+    _disable();
+
+    /* Check the bugcheck count */
+    if (!InterlockedDecrement((PLONG)&KeBugCheckCount))
+    {
+        /* There was only one, is the debugger disabled? */
+        if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
+        {
+            /* Enable the debugger */
+            KdInitSystem(0, NULL);
+        }
+    }
+
+    /* Break in the debugger */
+    KiBugCheckDebugBreak(DBG_STATUS_FATAL);
+}
+
 /* EOF */