- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / ntoskrnl / ke / bug.c
index 72ad4e3..dd19977 100644 (file)
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/ke/bug.c
- * PURPOSE:         Graceful system shutdown if a bug is detected
- * 
- * PROGRAMMERS:     Alex Ionescu - Rewrote Bugcheck Routines and implemented Reason Callbacks.
- *                  David Welch (welch@cwcom.net)
- *                  Phillip Susi
+ * PURPOSE:         Bugcheck Support
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
-/* GLOBALS ******************************************************************/
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, KiInitializeBugCheck)
+#endif
+
+/* GLOBALS *******************************************************************/
+
+LIST_ENTRY KeBugcheckCallbackListHead;
+LIST_ENTRY KeBugcheckReasonCallbackListHead;
+KSPIN_LOCK BugCheckCallbackLock;
+ULONG KeBugCheckActive, KeBugCheckOwner;
+LONG KeBugCheckOwnerRecursionCount;
+PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
+ULONG KeBugCheckCount = 1;
+ULONG KiHardwareTrigger;
+PUNICODE_STRING KiBugCheckDriver;
+ULONG_PTR KiBugCheckData[5];
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+BOOLEAN
+NTAPI
+KiRosPrintAddress(PVOID address)
+{
+    PLIST_ENTRY current_entry;
+    PLDR_DATA_TABLE_ENTRY current;
+    extern LIST_ENTRY PsLoadedModuleList;
+    ULONG_PTR RelativeAddress;
+    ULONG i = 0;
+
+    do
+    {
+        current_entry = PsLoadedModuleList.Flink;
+
+        while (current_entry != &PsLoadedModuleList)
+        {
+            current = CONTAINING_RECORD(current_entry,
+                                        LDR_DATA_TABLE_ENTRY,
+                                        InLoadOrderLinks);
+
+            if (address >= (PVOID)current->DllBase &&
+                address < (PVOID)((ULONG_PTR)current->DllBase +
+                                             current->SizeOfImage))
+            {
+                RelativeAddress = (ULONG_PTR)address -
+                                  (ULONG_PTR)current->DllBase;
+                DbgPrint("<%wZ: %x>", &current->FullDllName, RelativeAddress);
+                return(TRUE);
+            }
+            current_entry = current_entry->Flink;
+        }
+    } while(++i <= 1);
+
+    return(FALSE);
+}
+
+VOID
+NTAPI
+KeRosDumpStackFrames(IN PULONG Frame OPTIONAL,
+                     IN ULONG FrameCount OPTIONAL)
+{
+    ULONG Frames[32];
+    ULONG i, Addr;
+
+    /* If the caller didn't ask, assume 32 frames */
+    if (!FrameCount) FrameCount = 32;
+
+    /* Get the current frames */
+    FrameCount = RtlCaptureStackBackTrace(2, FrameCount, (PVOID*)Frames, NULL);
+
+    /* Now loop them (skip the two. One for the dumper, one for the caller) */
+    for (i = 0; i < FrameCount; i++)
+    {
+        /* Get the EIP */
+        Addr = Frames[i];
+
+        /* If we had a custom frame, make sure we've reached it first */
+        if ((Frame) && (Frame[1] == Addr))
+        {
+            Frame = NULL;
+        }
+        else if (Frame)
+        {
+            /* Skip this entry */
+            continue;
+        }
+
+        /* Print it out */
+        if (!KeRosPrintAddress((PVOID)Addr)) DbgPrint("<%X>", Addr);
 
-static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
-static LIST_ENTRY BugcheckReasonCallbackListHead = {NULL,NULL};
-static ULONG InBugCheck;
-static PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
-static ULONG KeBugCheckCount = 1;
+        /* Go to the next frame */
+        DbgPrint("\n");
+    }
 
-/* FUNCTIONS *****************************************************************/
+    /* Finish the output */
+    DbgPrint("\n");
+}
 
 VOID
 INIT_FUNCTION
+NTAPI
 KiInitializeBugCheck(VOID)
 {
     PRTL_MESSAGE_RESOURCE_DATA BugCheckData;
     LDR_RESOURCE_INFO ResourceInfo;
     PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
     NTSTATUS Status;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
 
-    /* Initialize Callbadk Listhead and State */
-    InitializeListHead(&BugcheckCallbackListHead);
-    InitializeListHead(&BugcheckReasonCallbackListHead);
-    InBugCheck = 0;
+    /* Get the kernel entry */
+    LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
+                                 LDR_DATA_TABLE_ENTRY,
+                                 InLoadOrderLinks);
 
     /* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
     ResourceInfo.Type = 11;
     ResourceInfo.Name = 1;
     ResourceInfo.Language = 9;
-    
+
     /* Do the lookup. */
-    Status = LdrFindResource_U((PVOID)KERNEL_BASE,
+    Status = LdrFindResource_U(LdrEntry->DllBase,
                                &ResourceInfo,
                                RESOURCE_DATA_LEVEL,
                                &ResourceDataEntry);
-    
+
     /* Make sure it worked */
-    if (NT_SUCCESS(Status)) {
-        
-        DPRINT1("Found Bugcheck Resource Data!\n");
-        
+    if (NT_SUCCESS(Status))
+    {
         /* Now actually get a pointer to it */
-        Status = LdrAccessResource((PVOID)KERNEL_BASE,
+        Status = LdrAccessResource(LdrEntry->DllBase,
                                    ResourceDataEntry,
                                    (PVOID*)&BugCheckData,
                                    NULL);
-        
-        /* Make sure it worked */
-        if (NT_SUCCESS(Status)) {
+        if (NT_SUCCESS(Status)) KiBugCodeMessages = BugCheckData;
+    }
+}
+
+VOID
+NTAPI
+KeGetBugMessageText(IN ULONG BugCheckCode,
+                    OUT PANSI_STRING OutputString OPTIONAL)
+{
+    ULONG i;
+    ULONG IdOffset;
+    ULONG_PTR MessageEntry;
+    PCHAR BugCode;
+
+    /* Find the message. This code is based on RtlFindMesssage */
+    for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++)
+    {
+        /* 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;
+            IdOffset = BugCheckCode - KiBugCodeMessages->Blocks[i].LowId;
+
+            /* Get offset to ID */
+            for (i = 0; i < IdOffset; i++)
+            {
+                /* Advance in the Entries */
+                MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->
+                                Length;
+            }
+
+            /* Get the final Code */
+            BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
+            i = strlen(BugCode);
+
+            /* Return it in the OutputString */
+            if (OutputString)
+            {
+                OutputString->Buffer = BugCode;
+                OutputString->Length = i + 1;
+                OutputString->MaximumLength = i + 1;
+            }
+            else
+            {
+                /* Direct Output to Screen */
+                InbvDisplayString(BugCode);
+                InbvDisplayString("\r");
+                break;
+            }
+        }
+    }
+}
+
+VOID
+NTAPI
+KiDoBugCheckCallbacks(VOID)
+{
+    PKBUGCHECK_CALLBACK_RECORD CurrentRecord;
+    PLIST_ENTRY ListHead, NextEntry, LastEntry;
+    ULONG_PTR Checksum;
+
+    /* First make sure that the list is Initialized... it might not be */
+    ListHead = &KeBugcheckCallbackListHead;
+    if ((ListHead->Flink) && (ListHead->Blink))
+    {
+        /* Loop the list */
+        LastEntry = ListHead;
+        NextEntry = ListHead->Flink;
+        while (NextEntry != ListHead)
+        {
+            /* Get the reord */
+            CurrentRecord = CONTAINING_RECORD(NextEntry,
+                                              KBUGCHECK_CALLBACK_RECORD,
+                                              Entry);
+
+            /* Validate it */
+            if (CurrentRecord->Entry.Blink != LastEntry) return;
+            Checksum = (ULONG_PTR)CurrentRecord->CallbackRoutine;
+            Checksum += (ULONG_PTR)CurrentRecord->Buffer;
+            Checksum += (ULONG_PTR)CurrentRecord->Length;
+            Checksum += (ULONG_PTR)CurrentRecord->Component;
+
+            /* Make sure it's inserted and valitdated */
+            if ((CurrentRecord->State == BufferInserted) &&
+                (CurrentRecord->Checksum == Checksum))
+            {
+                /* Call the routine */
+                CurrentRecord->State = BufferStarted;
+                (CurrentRecord->CallbackRoutine)(CurrentRecord->Buffer,
+                                                 CurrentRecord->Length);
+                CurrentRecord->State = BufferFinished;
+            }
+
+            /* Go to the next entry */
+            LastEntry = NextEntry;
+            NextEntry = NextEntry->Flink;
+        }
+    }
+}
+
+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)
+    {
+        /* 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;
+            }
+        }
+    }
+
+    /* Return the base address */
+    return EipBase;
+}
+
+PCHAR
+NTAPI
+KeBugCheckUnicodeToAnsi(IN PUNICODE_STRING Unicode,
+                        OUT PCHAR Ansi,
+                        IN ULONG Length)
+{
+    PCHAR p;
+    PWCHAR pw;
+    ULONG i;
+
+    /* Set length and normalize it */
+    i = Unicode->Length / sizeof(WCHAR);
+    i = min(i, Length - 1);
+
+    /* Set source and destination, and copy */
+    pw = Unicode->Buffer;
+    p = Ansi;
+    while (i--) *p++ = (CHAR)*pw++;
+
+    /* Null terminate and return */
+    *p = ANSI_NULL;
+    return Ansi;
+}
+
+VOID
+NTAPI
+KiDumpParameterImages(IN PCHAR Message,
+                      IN PULONG_PTR Parameters,
+                      IN ULONG ParameterCount,
+                      IN PKE_BUGCHECK_UNICODE_TO_ANSI ConversionRoutine)
+{
+    ULONG i;
+    BOOLEAN InSystem;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PVOID ImageBase;
+    PUNICODE_STRING DriverName;
+    CHAR AnsiName[32];
+    PIMAGE_NT_HEADERS NtHeader;
+    ULONG TimeStamp;
+    BOOLEAN FirstRun = TRUE;
+
+    /* Loop parameters */
+    for (i = 0; i < ParameterCount; i++)
+    {
+        /* Get the base for this parameter */
+        ImageBase = KiPcToFileHeader((PVOID)Parameters[i],
+                                     &LdrEntry,
+                                     FALSE,
+                                     &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));
+        }
+        else
+        {
+            /* Get the NT Headers and Timestamp */
+            NtHeader = RtlImageNtHeader(LdrEntry->DllBase);
+            TimeStamp = NtHeader->FileHeader.TimeDateStamp;
+
+            /* Convert the driver name */
+            DriverName = &LdrEntry->BaseDllName;
+            ConversionRoutine(&LdrEntry->BaseDllName,
+                              AnsiName,
+                              sizeof(AnsiName));
+        }
+
+        /* Format driver name */
+        sprintf(Message,
+                "%s**  %12s - Address %p base at %p, DateStamp %08lx\n",
+                FirstRun ? "\r\n*":"*",
+                AnsiName,
+                (PVOID)Parameters[i],
+                ImageBase,
+                TimeStamp);
+
+        /* Check if we only had one parameter */
+        if (ParameterCount <= 1)
+        {
+            /* Then just save the name */
+            KiBugCheckDriver = DriverName;
+        }
+        else
+        {
+            /* Otherwise, display the message */
+            InbvDisplayString(Message);
+        }
+
+        /* Loop again */
+        FirstRun = FALSE;
+    }
+}
+
+VOID
+NTAPI
+KiDisplayBlueScreen(IN ULONG MessageId,
+                    IN BOOLEAN IsHardError,
+                    IN PCHAR HardErrCaption OPTIONAL,
+                    IN PCHAR HardErrMessage OPTIONAL,
+                    IN PCHAR Message)
+{
+    CHAR AnsiName[75];
+
+    /* Check if bootvid is installed */
+    if (InbvIsBootDriverInstalled())
+    {
+        /* Acquire ownership and reset the display */
+        InbvAcquireDisplayOwnership();
+        InbvResetDisplay();
+
+        /* Display blue screen */
+        InbvSolidColorFill(0, 0, 639, 479, 4);
+        InbvSetTextColor(15);
+        InbvInstallDisplayStringFilter(NULL);
+        InbvEnableDisplayString(TRUE);
+        InbvSetScrollRegion(0, 0, 639, 479);
+    }
+
+    /* Check if this is a hard error */
+    if (IsHardError)
+    {
+        /* Display caption and message */
+        if (HardErrCaption) InbvDisplayString(HardErrCaption);
+        if (HardErrMessage) InbvDisplayString(HardErrMessage);
+    }
+
+    /* Begin the display */
+    InbvDisplayString("\r\n");
+
+    /* Print out initial message */
+    KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO, NULL);
+    InbvDisplayString("\r\n\r\n");
+
+    /* Check if we have a driver */
+    if (KiBugCheckDriver)
+    {
+        /* Print out into to driver name */
+        KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL);
+
+        /* Convert and print out driver name */
+        KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName));
+        InbvDisplayString(" ");
+        InbvDisplayString(AnsiName);
+        InbvDisplayString("\r\n\r\n");
+    }
+
+    /* Check if this is the generic message */
+    if (MessageId == BUGCODE_PSS_MESSAGE)
+    {
+        /* It is, so get the bug code string as well */
+        KeGetBugMessageText(KiBugCheckData[0], NULL);
+        InbvDisplayString("\r\n\r\n");
+    }
+
+    /* Print second introduction message */
+    KeGetBugMessageText(PSS_MESSAGE_INTRO, NULL);
+    InbvDisplayString("\r\n\r\n");
+
+    /* Get the bug code string */
+    KeGetBugMessageText(MessageId, NULL);
+    InbvDisplayString("\r\n\r\n");
+
+    /* Print message for technical information */
+    KeGetBugMessageText(BUGCHECK_TECH_INFO, NULL);
+
+    /* Show the techincal Data */
+    sprintf(AnsiName,
+            "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
+            KiBugCheckData[0],
+            (PVOID)KiBugCheckData[1],
+            (PVOID)KiBugCheckData[2],
+            (PVOID)KiBugCheckData[3],
+            (PVOID)KiBugCheckData[4]);
+    InbvDisplayString(AnsiName);
+
+    /* Check if we have a driver*/
+    if (KiBugCheckDriver)
+    {
+        /* Display technical driver data */
+        InbvDisplayString(Message);
+    }
+    else
+    {
+        /* Dump parameter information */
+        KiDumpParameterImages(Message,
+                              (PVOID)&KiBugCheckData[1],
+                              4,
+                              KeBugCheckUnicodeToAnsi);
+    }
+}
+
+VOID
+NTAPI
+KeBugCheckWithTf(IN ULONG BugCheckCode,
+                 IN ULONG_PTR BugCheckParameter1,
+                 IN ULONG_PTR BugCheckParameter2,
+                 IN ULONG_PTR BugCheckParameter3,
+                 IN ULONG_PTR BugCheckParameter4,
+                 IN PKTRAP_FRAME TrapFrame)
+{
+    PKPRCB Prcb = KeGetCurrentPrcb();
+    CONTEXT Context;
+    ULONG MessageId;
+    CHAR AnsiName[128];
+    BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE;
+    PCHAR HardErrCaption = NULL, HardErrMessage = NULL;
+    PVOID Eip = NULL, Memory;
+    PVOID DriverBase;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PULONG_PTR HardErrorParameters;
+    KIRQL OldIrql;
+#ifdef CONFIG_SMP
+    LONG i = 0;
+#endif
+
+    /* Set active bugcheck */
+    KeBugCheckActive = TRUE;
+    KiBugCheckDriver = NULL;
+
+    /* Check if this is power failure simulation */
+    if (BugCheckCode == POWER_FAILURE_SIMULATE)
+    {
+        /* Call the Callbacks and reboot */;
+        KiDoBugCheckCallbacks();
+        HalReturnToFirmware(HalRebootRoutine);
+    }
+
+    /* Save the IRQL and set hardware trigger */
+    Prcb->DebuggerSavedIRQL = KeGetCurrentIrql();
+    InterlockedIncrement((PLONG)&KiHardwareTrigger);
+
+    /* Capture the CPU Context */
+    RtlCaptureContext(&Prcb->ProcessorState.ContextFrame);
+    KiSaveProcessorControlState(&Prcb->ProcessorState);
+    Context = Prcb->ProcessorState.ContextFrame;
+
+    /* FIXME: Call the Watchdog if it's registered */
+
+    /* Check which bugcode this is */
+    switch (BugCheckCode)
+    {
+        /* These bug checks already have detailed messages, keep them */
+        case UNEXPECTED_KERNEL_MODE_TRAP:
+        case DRIVER_CORRUPTED_EXPOOL:
+        case ACPI_BIOS_ERROR:
+        case ACPI_BIOS_FATAL_ERROR:
+        case THREAD_STUCK_IN_DEVICE_DRIVER:
+        case DATA_BUS_ERROR:
+        case FAT_FILE_SYSTEM:
+        case NO_MORE_SYSTEM_PTES:
+        case INACCESSIBLE_BOOT_DEVICE:
+
+            /* Keep the same code */
+            MessageId = BugCheckCode;
+            break;
+
+        /* Check if this is a kernel-mode exception */
+        case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
+        //case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
+        case KMODE_EXCEPTION_NOT_HANDLED:
+
+            /* Use the generic text message */
+            MessageId = KMODE_EXCEPTION_NOT_HANDLED;
+            break;
+
+        /* File-system errors */
+        case NTFS_FILE_SYSTEM:
+
+            /* Use the generic message for FAT */
+            MessageId = FAT_FILE_SYSTEM;
+            break;
+
+        /* Check if this is a coruption of the Mm's Pool */
+        case DRIVER_CORRUPTED_MMPOOL:
+
+            /* Use generic corruption message */
+            MessageId = DRIVER_CORRUPTED_EXPOOL;
+            break;
+
+        /* Check if this is a signature check failure */
+        case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE:
+
+            /* Use the generic corruption message */
+            MessageId = BUGCODE_PSS_MESSAGE_SIGNATURE;
+            break;
+
+        /* All other codes */
+        default:
 
-            DPRINT1("Got Pointer to Bugcheck Resource Data!\n");
-            KiBugCodeMessages = BugCheckData;
+            /* Use the default bugcheck message */
+            MessageId = BUGCODE_PSS_MESSAGE;
+            break;
+    }
+
+    /* Save bugcheck data */
+    KiBugCheckData[0] = BugCheckCode;
+    KiBugCheckData[1] = BugCheckParameter1;
+    KiBugCheckData[2] = BugCheckParameter2;
+    KiBugCheckData[3] = BugCheckParameter3;
+    KiBugCheckData[4] = BugCheckParameter4;
+
+    /* Now check what bugcheck this is */
+    switch (BugCheckCode)
+    {
+        /* Invalid access to R/O memory or Unhandled KM Exception */
+        case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
+        case ATTEMPTED_WRITE_TO_READONLY_MEMORY:
+        case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY:
+
+            /* Check if we have a trap frame */
+            if (!TrapFrame)
+            {
+                /* Use parameter 3 as a trap frame, if it exists */
+                if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
+            }
+
+            /* Check if we got one now and if we need to get EIP */
+            if ((TrapFrame) &&
+                (BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED))
+            {
+                /* Get EIP */
+                Eip = (PVOID)TrapFrame->Eip;
+            }
+            break;
+
+        /* Wrong IRQL */
+        case IRQL_NOT_LESS_OR_EQUAL:
+
+            /*
+             * The NT kernel has 3 special sections:
+             * MISYSPTE, POOLMI and POOLCODE. The bug check code can
+             * determine in which of these sections this bugcode happened
+             * and provide a more detailed analysis. For now, we don't.
+             */
+
+            /* Eip is in parameter 4 */
+            Eip = (PVOID)BugCheckParameter4;
+
+            /* Get the driver base */
+            DriverBase = KiPcToFileHeader(Eip, &LdrEntry, FALSE, &IsSystem);
+            if (IsSystem)
+            {
+                /*
+                 * The error happened inside the kernel or HAL.
+                 * Get the memory address that was being referenced.
+                 */
+                Memory = (PVOID)BugCheckParameter1;
+
+                /* Find to which driver it belongs */
+                DriverBase = KiPcToFileHeader(Memory,
+                                              &LdrEntry,
+                                              TRUE,
+                                              &IsSystem);
+                if (DriverBase)
+                {
+                    /* Get the driver name and update the bug code */
+                    KiBugCheckDriver = &LdrEntry->BaseDllName;
+                    KiBugCheckData[0] = DRIVER_PORTION_MUST_BE_NONPAGED;
+                }
+                else
+                {
+                    /* Find the driver that unloaded at this address */
+                    KiBugCheckDriver = NULL; // FIXME: ROS can't locate
+
+                    /* Check if the cause was an unloaded driver */
+                    if (KiBugCheckDriver)
+                    {
+                        /* Update bug check code */
+                        KiBugCheckData[0] =
+                            SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD;
+                    }
+                }
+            }
+            else
+            {
+                /* Update the bug check code */
+                KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
+            }
+
+            /* Clear EIP so we don't look it up later */
+            Eip = NULL;
+            break;
+
+        /* Hard error */
+        case FATAL_UNHANDLED_HARD_ERROR:
+
+            /* Copy bug check data from hard error */
+            HardErrorParameters = (PULONG_PTR)BugCheckParameter2;
+            KiBugCheckData[0] = BugCheckParameter1;
+            KiBugCheckData[1] = HardErrorParameters[0];
+            KiBugCheckData[2] = HardErrorParameters[1];
+            KiBugCheckData[3] = HardErrorParameters[2];
+            KiBugCheckData[4] = HardErrorParameters[3];
+
+            /* Remember that this is hard error and set the caption/message */
+            IsHardError = TRUE;
+            HardErrCaption = (PCHAR)BugCheckParameter3;
+            HardErrMessage = (PCHAR)BugCheckParameter4;
+            break;
+
+        /* Page fault */
+        case PAGE_FAULT_IN_NONPAGED_AREA:
+
+            /* Assume no driver */
+            DriverBase = NULL;
+
+            /* Check if we have a trap frame */
+            if (!TrapFrame)
+            {
+                /* We don't, use parameter 3 if possible */
+                if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
+            }
+
+            /* Check if we have a frame now */
+            if (TrapFrame)
+            {
+                /* Get EIP */
+                Eip = (PVOID)TrapFrame->Eip;
+                KiBugCheckData[3] = (ULONG)Eip;
+
+                /* Find out if was in the kernel or drivers */
+                DriverBase = KiPcToFileHeader(Eip,
+                                              &LdrEntry,
+                                              FALSE,
+                                              &IsSystem);
+            }
+
+            /*
+             * Now we should check if this happened in:
+             * 1) Special Pool 2) Free Special Pool 3) Session Pool
+             * and update the bugcheck code appropriately.
+             */
+
+            /* Check if we didn't have a driver base */
+            if (!DriverBase)
+            {
+                /* Find the driver that unloaded at this address */
+                KiBugCheckDriver = NULL; // FIXME: ROS can't locate
+
+                /* Check if the cause was an unloaded driver */
+                if (KiBugCheckDriver)
+                {
+                    KiBugCheckData[0] =
+                        DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS;
+                }
+            }
+            break;
+
+        /* Check if the driver forgot to unlock pages */
+        case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
+
+            /* EIP is in parameter 1 */
+            Eip = (PVOID)BugCheckParameter1;
+            break;
+
+        /* Check if the driver consumed too many PTEs */
+        case DRIVER_USED_EXCESSIVE_PTES:
+
+            /* Loader entry is in parameter 1 */
+            LdrEntry = (PVOID)BugCheckParameter1;
+            KiBugCheckDriver = &LdrEntry->BaseDllName;
+            break;
+
+        /* Check if the driver has a stuck thread */
+        case THREAD_STUCK_IN_DEVICE_DRIVER:
+
+            /* The name is in Parameter 3 */
+            KiBugCheckDriver = (PVOID)BugCheckParameter3;
+            break;
+
+        /* Anything else */
+        default:
+            break;
+    }
+
+    /* Do we have a driver name? */
+    if (KiBugCheckDriver)
+    {
+        /* Convert it to ANSI */
+        KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName));
+    }
+    else
+    {
+        /* Do we have an EIP? */
+        if (Eip)
+        {
+            /* Dump image name */
+            KiDumpParameterImages(AnsiName,
+                                  (PULONG_PTR)&Eip,
+                                  1,
+                                  KeBugCheckUnicodeToAnsi);
         }
     }
+
+    /* Check if we need to save the context for KD */
+
+    /* Check if a debugger is connected */
+    if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled))
+    {
+        /* Crash on the debugger console */
+        DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
+                 "                       (0x%p,0x%p,0x%p,0x%p)\n\n",
+                 KiBugCheckData[0],
+                 KiBugCheckData[1],
+                 KiBugCheckData[2],
+                 KiBugCheckData[3],
+                 KiBugCheckData[4]);
+
+        /* Check if the debugger isn't currently connected */
+        if (!KdDebuggerNotPresent)
+        {
+            /* Check if we have a driver to blame */
+            if (KiBugCheckDriver)
+            {
+                /* Dump it */
+                DbgPrint("Driver at fault: %s.\n", AnsiName);
+            }
+
+            /* Check if this was a hard error */
+            if (IsHardError)
+            {
+                /* Print caption and message */
+                if (HardErrCaption) DbgPrint(HardErrCaption);
+                if (HardErrMessage) DbgPrint(HardErrMessage);
+            }
+
+            /* 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);
+        }
+    }
+
+    /* 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))
+    {
+#ifdef CONFIG_SMP
+        /* Set CPU that is bug checking now */
+        KeBugCheckOwner = Prcb->Number;
+
+        /* Freeze the other CPUs */
+        for (i = 0; i < KeNumberProcessors; i++)
+        {
+            if (i != (LONG)KeGetCurrentProcessorNumber())
+            {
+                /* Send the IPI and give them one second to catch up */
+                KiIpiSendRequest(1 << i, IPI_FREEZE);
+                KeStallExecutionProcessor(1000000);
+            }
+        }
+#endif
+
+        /* Display the BSOD */
+        KiDisplayBlueScreen(MessageId,
+                            IsHardError,
+                            HardErrCaption,
+                            HardErrMessage,
+                            AnsiName);
+
+        /* Check if the debugger is disabled but we can enable it */
+        //if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
+        {
+            /* Enable it */
+            //KdEnableDebuggerWithLock(FALSE);
+        }
+        //else
+        {
+            /* Otherwise, print the last line */
+            InbvDisplayString("\r\n");
+        }
+
+        /* Save the context */
+        Prcb->ProcessorState.ContextFrame = Context;
+
+        /* FIXME: Support Triage Dump */
+
+        /* Write the crash dump */
+        MmDumpToPagingFile(KiBugCheckData[4],
+                           KiBugCheckData[0],
+                           KiBugCheckData[1],
+                           KiBugCheckData[2],
+                           KiBugCheckData[3],
+                           TrapFrame);
+    }
+    else
+    {
+        /* Increase recursion count */
+        KeBugCheckOwnerRecursionCount++;
+        if (KeBugCheckOwnerRecursionCount == 2)
+        {
+            /* Break in the debugger */
+            KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
+        }
+        else if (KeBugCheckOwnerRecursionCount > 2)
+        {
+            /* Halt the CPU */
+            for (;;) Ke386HaltProcessor();
+        }
+    }
+
+    /* Call the Callbacks */
+    KiDoBugCheckCallbacks();
+
+    /* FIXME: Call Watchdog if enabled */
+
+    /* Check if we have to reboot */
+    if (Reboot)
+    {
+        /* Unload symbols */
+        DbgUnLoadImageSymbols(NULL, NtCurrentProcess(), 0);
+        HalReturnToFirmware(HalRebootRoutine);
+    }
+
+    /* Attempt to break in the debugger (otherwise halt CPU) */
+    KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
 }
 
+/* PUBLIC FUNCTIONS **********************************************************/
+
 /*
  * @implemented
  */
-BOOLEAN 
-STDCALL
-KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
+BOOLEAN
+NTAPI
+KeDeregisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
 {
     KIRQL OldIrql;
     BOOLEAN Status = FALSE;
-    
+
     /* Raise IRQL to High */
     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-    
-    /* Check the Current State */
-    if (CallbackRecord->State == BufferInserted) {
 
+    /* Check the Current State */
+    if (CallbackRecord->State == BufferInserted)
+    {
         /* Reset state and remove from list */
         CallbackRecord->State = BufferEmpty;
         RemoveEntryList(&CallbackRecord->Entry);
-        
         Status = TRUE;
     }
 
@@ -102,22 +991,22 @@ KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
  * @implemented
  */
 BOOLEAN
-STDCALL
-KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
+NTAPI
+KeDeregisterBugCheckReasonCallback(
+    IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
 {
     KIRQL OldIrql;
     BOOLEAN Status = FALSE;
-    
+
     /* Raise IRQL to High */
     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-    
-    /* Check the Current State */
-    if (CallbackRecord->State == BufferInserted) {
 
+    /* Check the Current State */
+    if (CallbackRecord->State == BufferInserted)
+    {
         /* Reset state and remove from list */
         CallbackRecord->State = BufferEmpty;
         RemoveEntryList(&CallbackRecord->Entry);
-        
         Status = TRUE;
     }
 
@@ -129,31 +1018,30 @@ KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD Callback
 /*
  * @implemented
  */
-BOOLEAN 
-STDCALL
-KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
-                           PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
-                           PVOID Buffer,
-                           ULONG Length,
-                           PUCHAR Component)
+BOOLEAN
+NTAPI
+KeRegisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
+                           IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
+                           IN PVOID Buffer,
+                           IN ULONG Length,
+                           IN PUCHAR Component)
 {
     KIRQL OldIrql;
     BOOLEAN Status = FALSE;
-    
+
     /* Raise IRQL to High */
     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-    
+
     /* Check the Current State first so we don't double-register */
-    if (CallbackRecord->State == BufferEmpty) {
-        
+    if (CallbackRecord->State == BufferEmpty)
+    {
         /* Set the Callback Settings and insert into the list */
         CallbackRecord->Length = Length;
         CallbackRecord->Buffer = Buffer;
         CallbackRecord->Component = Component;
         CallbackRecord->CallbackRoutine = CallbackRoutine;
         CallbackRecord->State = BufferInserted;
-        InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
-    
+        InsertTailList(&KeBugcheckCallbackListHead, &CallbackRecord->Entry);
         Status = TRUE;
     }
 
@@ -166,28 +1054,29 @@ KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
  * @implemented
  */
 BOOLEAN
-STDCALL
-KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
-                                 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
-                                 IN KBUGCHECK_CALLBACK_REASON Reason,
-                                 IN PUCHAR Component)
+NTAPI
+KeRegisterBugCheckReasonCallback(
+    IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
+    IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
+    IN KBUGCHECK_CALLBACK_REASON Reason,
+    IN PUCHAR Component)
 {
     KIRQL OldIrql;
     BOOLEAN Status = FALSE;
-    
+
     /* Raise IRQL to High */
     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-    
+
     /* Check the Current State first so we don't double-register */
-    if (CallbackRecord->State == BufferEmpty) {
-        
+    if (CallbackRecord->State == BufferEmpty)
+    {
         /* Set the Callback Settings and insert into the list */
         CallbackRecord->Component = Component;
         CallbackRecord->CallbackRoutine = CallbackRoutine;
         CallbackRecord->State = BufferInserted;
         CallbackRecord->Reason = Reason;
-        InsertTailList(&BugcheckReasonCallbackListHead, &CallbackRecord->Entry);
-    
+        InsertTailList(&KeBugcheckReasonCallbackListHead,
+                       &CallbackRecord->Entry);
         Status = TRUE;
     }
 
@@ -196,284 +1085,35 @@ KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRe
     return Status;
 }
 
-VOID
-STDCALL
-KeGetBugMessageText(ULONG BugCheckCode, PANSI_STRING OutputString)
-{
-    ULONG i;
-    ULONG IdOffset;
-    ULONG_PTR MessageEntry;
-    PCHAR BugCode;
-    
-    /* Find the message. This code is based on RtlFindMesssage -- Alex */
-    for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++)  {
-        
-        /* Check if the ID Matches */
-        if ((BugCheckCode >= KiBugCodeMessages->Blocks[i].LowId) &&
-            (BugCheckCode <= KiBugCodeMessages->Blocks[i].HighId)) {
-            
-            /* Get Offset to Entry */
-            MessageEntry = (ULONG_PTR)KiBugCodeMessages + KiBugCodeMessages->Blocks[i].OffsetToEntries;
-            IdOffset = BugCheckCode - KiBugCodeMessages->Blocks[i].LowId;
-            
-            /* Get offset to ID */
-            for (i = 0; i < IdOffset; i++) {
-             
-                /* Advance in the Entries */   
-                MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Length;
-            }
-            
-            /* Get the final Code */
-            BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
-            
-            /* Return it in the OutputString */
-            if (OutputString) {
-            
-                OutputString->Buffer = BugCode;
-                OutputString->Length = strlen(BugCode) + 1;
-                OutputString->MaximumLength = strlen(BugCode) + 1;
-            
-            } else {
-            
-                /* Direct Output to Screen */
-                DbgPrint("%s\n", BugCode);
-                break;
-            }
-        }
-    }
-}
-
-VOID
-STDCALL
-KiDoBugCheckCallbacks(VOID)
-{
-    PKBUGCHECK_CALLBACK_RECORD CurrentRecord;
-    PLIST_ENTRY ListHead;
-    PLIST_ENTRY NextEntry;
-    
-    /* FIXME: Check Checksum and add support for WithReason Callbacks */
-    
-    /* First make sure that the list is Initialized... it might not be */
-    ListHead = &BugcheckCallbackListHead;
-    if (ListHead->Flink && ListHead->Blink) {
-    
-        /* Loop the list */
-        NextEntry = ListHead->Flink;
-        while (NextEntry != ListHead) {
-        
-            /* Get the Callback Record */
-            CurrentRecord = CONTAINING_RECORD(NextEntry, 
-                                              KBUGCHECK_CALLBACK_RECORD,
-                                              Entry);
-            
-            /* Make sure it's inserted */
-            if (CurrentRecord->State == BufferInserted) {
-            
-                /* Call the routine */
-                CurrentRecord->State = BufferStarted;
-                (CurrentRecord->CallbackRoutine)(CurrentRecord->Buffer, 
-                                                 CurrentRecord->Length);
-                CurrentRecord->State = BufferFinished;
-            }
-            
-            /* Move to next Entry */
-            NextEntry = NextEntry->Flink;
-        }
-    }
-}
-
-VOID 
-STDCALL
-KeBugCheckWithTf(ULONG BugCheckCode,
-                 ULONG BugCheckParameter1,
-                 ULONG BugCheckParameter2,
-                 ULONG BugCheckParameter3,
-                 ULONG BugCheckParameter4,
-                 PKTRAP_FRAME Tf)
-{
-    KIRQL OldIrql;
-    BOOLEAN GotExtendedCrashInfo = FALSE;
-    PVOID Address = 0;
-    PLIST_ENTRY CurrentEntry;
-    MODULE_TEXT_SECTION* CurrentSection = NULL;
-    extern LIST_ENTRY ModuleTextListHead;
-     
-    /* Make sure we're switching back to the blue screen and print messages on it */
-    HalReleaseDisplayOwnership();
-    if (KdpDebugMode.Gdb) KdpDebugMode.Screen = TRUE;
-    /* Try to find out who did this. For this, we need a Trap Frame.
-     * Note: Some special BSODs pass the Frame/EIP as a Param. MSDN has the
-     * info so it eventually needs to be supported. 
-     */
-    if (Tf) {
-        
-        /* For now, get Address from EIP */
-        Address = (PVOID)Tf->Eip;
-        
-        /* Try to get information on the module */
-        CurrentEntry = ModuleTextListHead.Flink;
-        while (CurrentEntry != &ModuleTextListHead && CurrentEntry != NULL) {
-            
-            /* Get the current Section */
-            CurrentSection = CONTAINING_RECORD(CurrentEntry, 
-                                               MODULE_TEXT_SECTION, 
-                                               ListEntry);
-
-            /* Check if this is the right one */
-            if ((Address != NULL && (Address >= (PVOID)CurrentSection->Base &&
-                 Address < (PVOID)(CurrentSection->Base + CurrentSection->Length)))) {
-
-                /* We got it */            
-                GotExtendedCrashInfo = TRUE;
-                break;
-            }
-            
-            /* Loop again */
-            CurrentEntry = CurrentEntry->Flink;
-        }
-    }
-       
-    /* Raise IRQL to HIGH_LEVEL */
-    Ke386DisableInterrupts();
-    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-
-    /* Unload the Kernel Adress Space if we own it */
-    if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
-        MmUnlockAddressSpace(MmGetKernelAddressSpace());
-     
-    /* FIXMEs: Use inbv to clear, fill and write to screen. */
-    
-    /* Show the STOP Message */
-    DbgPrint("A problem has been detected and ReactOS has been shut down to prevent "
-             "damage to your computer.\n\n");
-    /* Show the module name of who caused this */
-    if (GotExtendedCrashInfo) {
-    
-        DbgPrint("The problem seems to be caused by the following file: %S\n\n", CurrentSection->Name);
-    }
-
-    /* Find the Bug Code String */
-    KeGetBugMessageText(BugCheckCode, NULL);
-
-    /* Show the techincal Data */
-    DbgPrint("Technical information:\n\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\n\n",
-             BugCheckCode,
-             BugCheckParameter1,
-             BugCheckParameter2,
-             BugCheckParameter3,
-             BugCheckParameter4);
-
-    /* Show the module name and more data of who caused this */
-    if (GotExtendedCrashInfo) {
-    
-        DbgPrint("***    %S - Address 0x%p base at 0x%p, DateStamp 0x%x\n\n", 
-                 CurrentSection->Name,
-                 Address,
-                 CurrentSection->Base,
-                 0);
-    }
-    
-    /* There can only be one Bugcheck per Bootup */
-    if (!InterlockedDecrement(&KeBugCheckCount)) {
-
-#ifdef CONFIG_SMP
-        ULONG i;
-        /* Freeze the other CPUs */
-        for (i = 0; i < KeNumberProcessors; i++) {    
-            if (i != KeGetCurrentProcessorNumber()) {
-                
-                /* Send the IPI and give them one second to catch up */
-                KiIpiSendRequest(1 << i, IPI_REQUEST_FREEZE);
-                KeStallExecutionProcessor(1000000);
-            }
-        }
-#endif
-
-        /* Check if we got a Trap Frame */
-        if (Tf) {
-        
-            /* Dump it */
-            KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
-    
-        } else {
-        
-            /* We can only dump the frames */
-#if defined(__GNUC__)
-            KeDumpStackFrames((PULONG)__builtin_frame_address(0));
-#elif defined(_MSC_VER)
-            __asm push ebp
-            __asm call KeDumpStackFrames
-            __asm add esp, 4
-#else
-#error Unknown compiler for inline assembler
-#endif
-        }
-        
-        /* Call the Callbacks */;
-        KiDoBugCheckCallbacks();
-
-        /* Dump the BSOD to the Paging File */
-        MmDumpToPagingFile(BugCheckCode, 
-                           BugCheckParameter1, 
-                           BugCheckParameter2, 
-                           BugCheckParameter3,
-                           BugCheckParameter4, 
-                           Tf);
-
-        /* Wake up the Debugger */
-        if (KdDebuggerEnabled) {
-            Ke386EnableInterrupts();
-            DbgBreakPointWithStatus(DBG_STATUS_BUGCHECK_SECOND);
-            Ke386DisableInterrupts();
-        }
-    }
-
-    /* Halt this CPU now */
-    for (;;) Ke386HaltProcessor();
-}
-
 /*
  * @implemented
- *
- * FUNCTION: Brings the system down in a controlled manner when an 
- * inconsistency that might otherwise cause corruption has been detected
- * ARGUMENTS:
- *           BugCheckCode = Specifies the reason for the bug check
- *           BugCheckParameter[1-4] = Additional information about bug
- * RETURNS: Doesn't
  */
-VOID 
-STDCALL
-KeBugCheckEx(ULONG BugCheckCode,
-             ULONG BugCheckParameter1,
-             ULONG BugCheckParameter2,
-             ULONG BugCheckParameter3,
-             ULONG BugCheckParameter4)
+VOID
+NTAPI
+KeBugCheckEx(IN ULONG BugCheckCode,
+             IN ULONG_PTR BugCheckParameter1,
+             IN ULONG_PTR BugCheckParameter2,
+             IN ULONG_PTR BugCheckParameter3,
+             IN ULONG_PTR BugCheckParameter4)
 {
-    /* Call the Trap Frame version without a Trap Frame */
-    KeBugCheckWithTf(BugCheckCode, 
-                     BugCheckParameter1, 
+    /* Call the internal API */
+    KeBugCheckWithTf(BugCheckCode,
+                     BugCheckParameter1,
                      BugCheckParameter2,
-                     BugCheckParameter3, 
-                     BugCheckParameter4, 
+                     BugCheckParameter3,
+                     BugCheckParameter4,
                      NULL);
 }
 
 /*
  * @implemented
- *
- * FUNCTION: Brings the system down in a controlled manner when an 
- * inconsistency that might otherwise cause corruption has been detected
- * ARGUMENTS:
- *           BugCheckCode = Specifies the reason for the bug check
- * RETURNS: Doesn't
  */
-VOID STDCALL
+VOID
+NTAPI
 KeBugCheck(ULONG BugCheckCode)
 {
-  KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
+    /* Call the internal API */
+    KeBugCheckWithTf(BugCheckCode, 0, 0, 0, 0, NULL);
 }
 
 /* EOF */