ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

bug.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ke/bug.c
00005  * PURPOSE:         Bugcheck Support
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 #if defined (ALLOC_PRAGMA)
00016 #pragma alloc_text(INIT, KiInitializeBugCheck)
00017 #endif
00018 
00019 /* GLOBALS *******************************************************************/
00020 
00021 LIST_ENTRY KeBugcheckCallbackListHead;
00022 LIST_ENTRY KeBugcheckReasonCallbackListHead;
00023 KSPIN_LOCK BugCheckCallbackLock;
00024 ULONG KeBugCheckActive, KeBugCheckOwner;
00025 LONG KeBugCheckOwnerRecursionCount;
00026 PMESSAGE_RESOURCE_DATA KiBugCodeMessages;
00027 ULONG KeBugCheckCount = 1;
00028 ULONG KiHardwareTrigger;
00029 PUNICODE_STRING KiBugCheckDriver;
00030 ULONG_PTR KiBugCheckData[5];
00031 PKNMI_HANDLER_CALLBACK KiNmiCallbackListHead;
00032 KSPIN_LOCK KiNmiCallbackListLock;
00033 
00034 /* Bugzilla Reporting */
00035 UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion;
00036 UNICODE_STRING KeRosVideoBiosDate, KeRosVideoBiosVersion;
00037 
00038 /* PRIVATE FUNCTIONS *********************************************************/
00039 
00040 PVOID
00041 NTAPI
00042 KiPcToFileHeader(IN PVOID Pc,
00043                  OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
00044                  IN BOOLEAN DriversOnly,
00045                  OUT PBOOLEAN InKernel)
00046 {
00047     ULONG i = 0;
00048     PVOID ImageBase, PcBase = NULL;
00049     PLDR_DATA_TABLE_ENTRY Entry;
00050     PLIST_ENTRY ListHead, NextEntry;
00051 
00052     /* Check which list we should use */
00053     ListHead = (KeLoaderBlock) ? &KeLoaderBlock->LoadOrderListHead :
00054                                  &PsLoadedModuleList;
00055 
00056     /* Assume no */
00057     *InKernel = FALSE;
00058 
00059     /* Set list pointers and make sure it's valid */
00060     NextEntry = ListHead->Flink;
00061     if (NextEntry)
00062     {
00063         /* Start loop */
00064         while (NextEntry != ListHead)
00065         {
00066             /* Increase entry */
00067             i++;
00068 
00069             /* Check if this is a kernel entry and we only want drivers */
00070             if ((i <= 2) && (DriversOnly == TRUE))
00071             {
00072                 /* Skip it */
00073                 NextEntry = NextEntry->Flink;
00074                 continue;
00075             }
00076 
00077             /* Get the loader entry */
00078             Entry = CONTAINING_RECORD(NextEntry,
00079                                       LDR_DATA_TABLE_ENTRY,
00080                                       InLoadOrderLinks);
00081 
00082             /* Move to the next entry */
00083             NextEntry = NextEntry->Flink;
00084             ImageBase = Entry->DllBase;
00085 
00086             /* Check if this is the right one */
00087             if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
00088                 ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
00089             {
00090                 /* Return this entry */
00091                 *LdrEntry = Entry;
00092                 PcBase = ImageBase;
00093 
00094                 /* Check if this was a kernel or HAL entry */
00095                 if (i <= 2) *InKernel = TRUE;
00096                 break;
00097             }
00098         }
00099     }
00100 
00101     /* Return the base address */
00102     return PcBase;
00103 }
00104 
00105 PVOID
00106 NTAPI
00107 KiRosPcToUserFileHeader(IN PVOID Pc,
00108                         OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
00109 {
00110     PVOID ImageBase, PcBase = NULL;
00111     PLDR_DATA_TABLE_ENTRY Entry;
00112     PLIST_ENTRY ListHead, NextEntry;
00113 
00114     /*
00115      * We know this is valid because we should only be called after a
00116      * succesfull address from RtlWalkFrameChain for UserMode, which
00117      * validates everything for us.
00118      */
00119     ListHead = &KeGetCurrentThread()->
00120                Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList;
00121 
00122     /* Set list pointers and make sure it's valid */
00123     NextEntry = ListHead->Flink;
00124     if (NextEntry)
00125     {
00126         /* Start loop */
00127         while (NextEntry != ListHead)
00128         {
00129             /* Get the loader entry */
00130             Entry = CONTAINING_RECORD(NextEntry,
00131                                       LDR_DATA_TABLE_ENTRY,
00132                                       InLoadOrderLinks);
00133 
00134             /* Move to the next entry */
00135             NextEntry = NextEntry->Flink;
00136             ImageBase = Entry->DllBase;
00137 
00138             /* Check if this is the right one */
00139             if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
00140                 ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
00141             {
00142                 /* Return this entry */
00143                 *LdrEntry = Entry;
00144                 PcBase = ImageBase;
00145                 break;
00146             }
00147         }
00148     }
00149 
00150     /* Return the base address */
00151     return PcBase;
00152 }
00153 
00154 USHORT
00155 NTAPI
00156 KeRosCaptureUserStackBackTrace(IN ULONG FramesToSkip,
00157                                IN ULONG FramesToCapture,
00158                                OUT PVOID *BackTrace,
00159                                OUT PULONG BackTraceHash OPTIONAL)
00160 {
00161     PVOID Frames[2 * 64];
00162     ULONG FrameCount;
00163     ULONG Hash = 0, i;
00164 
00165     /* Skip a frame for the caller */
00166     FramesToSkip++;
00167 
00168     /* Don't go past the limit */
00169     if ((FramesToCapture + FramesToSkip) >= 128) return 0;
00170 
00171     /* Do the back trace */
00172     FrameCount = RtlWalkFrameChain(Frames, FramesToCapture + FramesToSkip, 1);
00173 
00174     /* Make sure we're not skipping all of them */
00175     if (FrameCount <= FramesToSkip) return 0;
00176 
00177     /* Loop all the frames */
00178     for (i = 0; i < FramesToCapture; i++)
00179     {
00180         /* Don't go past the limit */
00181         if ((FramesToSkip + i) >= FrameCount) break;
00182 
00183         /* Save this entry and hash it */
00184         BackTrace[i] = Frames[FramesToSkip + i];
00185         Hash += PtrToUlong(BackTrace[i]);
00186     }
00187 
00188     /* Write the hash */
00189     if (BackTraceHash) *BackTraceHash = Hash;
00190 
00191     /* Clear the other entries and return count */
00192     RtlFillMemoryUlong(Frames, 128, 0);
00193     return (USHORT)i;
00194 }
00195 
00196 
00197 VOID
00198 FASTCALL
00199 KeRosDumpStackFrameArray(IN PULONG_PTR Frames,
00200                          IN ULONG FrameCount)
00201 {
00202     ULONG i;
00203     ULONG_PTR Addr;
00204     BOOLEAN InSystem;
00205     PVOID p;
00206 
00207     /* GCC complaints that it may be used uninitialized */
00208     PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
00209 
00210     /* Loop them */
00211     for (i = 0; i < FrameCount; i++)
00212     {
00213         /* Get the EIP */
00214         Addr = Frames[i];
00215         if (!Addr)
00216         {
00217             break;
00218         }
00219 
00220         /* Get the base for this file */
00221         if (Addr > (ULONG_PTR)MmHighestUserAddress)
00222         {
00223             /* We are in kernel */
00224             p = KiPcToFileHeader((PVOID)Addr, &LdrEntry, FALSE, &InSystem);
00225         }
00226         else
00227         {
00228             /* We are in user land */
00229             p = KiRosPcToUserFileHeader((PVOID)Addr, &LdrEntry);
00230         }
00231         if (p)
00232         {
00233 #ifdef KDBG
00234             if (!KdbSymPrintAddress((PVOID)Addr, NULL))
00235 #endif
00236             {
00237                 CHAR AnsiName[64];
00238 
00239                 /* Convert module name to ANSI and print it */
00240                 KeBugCheckUnicodeToAnsi(&LdrEntry->BaseDllName,
00241                                         AnsiName,
00242                                         sizeof(AnsiName));
00243                 Addr -= (ULONG_PTR)LdrEntry->DllBase;
00244                 DbgPrint("<%s: %p>", AnsiName, (PVOID)Addr);
00245             }
00246         }
00247         else
00248         {
00249             /* Print only the address */
00250             DbgPrint("<%p>", (PVOID)Addr);
00251         }
00252 
00253         /* Go to the next frame */
00254         DbgPrint("\n");
00255     }
00256 }
00257 
00258 VOID
00259 NTAPI
00260 KeRosDumpStackFrames(IN PULONG_PTR Frame OPTIONAL,
00261                      IN ULONG FrameCount OPTIONAL)
00262 {
00263     ULONG_PTR Frames[32];
00264     ULONG RealFrameCount;
00265 
00266     /* If the caller didn't ask, assume 32 frames */
00267     if (!FrameCount || FrameCount > 32) FrameCount = 32;
00268 
00269     if (Frame)
00270     {
00271         /* Dump them */
00272         KeRosDumpStackFrameArray(Frame, FrameCount);
00273     }
00274     else
00275     {
00276         /* Get the current frames (skip the two. One for the dumper, one for the caller) */
00277         RealFrameCount = RtlCaptureStackBackTrace(2, FrameCount, (PVOID*)Frames, NULL);
00278 
00279         /* Dump them */
00280         KeRosDumpStackFrameArray(Frames, RealFrameCount);
00281 
00282         /* Count left for user mode? */
00283         if (FrameCount - RealFrameCount > 0)
00284         {
00285             /* Get the current frames */
00286             RealFrameCount = KeRosCaptureUserStackBackTrace(-1, FrameCount - RealFrameCount, (PVOID*)Frames, NULL);
00287 
00288             /* Dump them */
00289             KeRosDumpStackFrameArray(Frames, RealFrameCount);
00290         }
00291     }
00292 }
00293 
00294 VOID
00295 NTAPI
00296 KeRosDumpTriageForBugZillaReport(VOID)
00297 {
00298 #if 0
00299     extern BOOLEAN KiFastSystemCallDisable, KiSMTProcessorsPresent;
00300     extern ULONG KeI386MachineType, MxcsrFeatureMask;
00301     extern BOOLEAN Ke386Pae, Ke386NoExecute;
00302 
00303     DbgPrint("ReactOS has crashed! Please go to http://www.reactos.org/bugzilla/enter_bug.cgi to file a bug!\n");
00304     DbgPrint("\nHardware Information\n");
00305     DbgPrint("Processor Architecture: %d\n"
00306              "Feature Bits: %d\n"
00307              "System Call Disabled: %d\n"
00308              "NPX Present: %d\n"
00309              "MXCsr Mask: %d\n"
00310              "MXCsr Feature Mask: %d\n"
00311              "XMMI Present: %d\n"
00312              "FXSR Present: %d\n"
00313              "Machine Type: %d\n"
00314              "PAE: %d\n"
00315              "NX: %d\n"
00316              "Processors: %d\n"
00317              "Active Processors: %d\n"
00318              "Pentium LOCK Bug: %d\n"
00319              "Hyperthreading: %d\n"
00320              "CPU Manufacturer: %s\n"
00321              "CPU Name: %wZ\n"
00322              "CPUID: %d\n"
00323              "CPU Type: %d\n"
00324              "CPU Stepping: %d\n"
00325              "CPU Speed: %d\n"
00326              "CPU L2 Cache: %d\n"
00327              "BIOS Date: %wZ\n"
00328              "BIOS Version: %wZ\n"
00329              "Video BIOS Date: %wZ\n"
00330              "Video BIOS Version: %wZ\n"
00331              "Memory: %d\n",
00332              KeProcessorArchitecture,
00333              KeFeatureBits,
00334              KiFastSystemCallDisable,
00335              KeI386NpxPresent,
00336              KiMXCsrMask,
00337              MxcsrFeatureMask,
00338              KeI386XMMIPresent,
00339              KeI386FxsrPresent,
00340              KeI386MachineType,
00341              Ke386Pae,
00342              Ke386NoExecute,
00343              KeNumberProcessors,
00344              KeActiveProcessors,
00345              KiI386PentiumLockErrataPresent,
00346              KiSMTProcessorsPresent,
00347              KeGetCurrentPrcb()->VendorString,
00348              &KeRosProcessorName,
00349              KeGetCurrentPrcb()->CpuID,
00350              KeGetCurrentPrcb()->CpuType,
00351              KeGetCurrentPrcb()->CpuStep,
00352              KeGetCurrentPrcb()->MHz,
00353              ((PKIPCR)KeGetPcr())->SecondLevelCacheSize,
00354              &KeRosBiosDate,
00355              &KeRosBiosVersion,
00356              &KeRosVideoBiosDate,
00357              &KeRosVideoBiosVersion,
00358              MmNumberOfPhysicalPages * PAGE_SIZE);
00359 #endif
00360 }
00361 
00362 VOID
00363 INIT_FUNCTION
00364 NTAPI
00365 KiInitializeBugCheck(VOID)
00366 {
00367     PMESSAGE_RESOURCE_DATA BugCheckData;
00368     LDR_RESOURCE_INFO ResourceInfo;
00369     PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
00370     NTSTATUS Status;
00371     PLDR_DATA_TABLE_ENTRY LdrEntry;
00372 
00373     /* Get the kernel entry */
00374     LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
00375                                  LDR_DATA_TABLE_ENTRY,
00376                                  InLoadOrderLinks);
00377 
00378     /* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
00379     ResourceInfo.Type = 11;
00380     ResourceInfo.Name = 1;
00381     ResourceInfo.Language = 9;
00382 
00383     /* Do the lookup. */
00384     Status = LdrFindResource_U(LdrEntry->DllBase,
00385                                &ResourceInfo,
00386                                RESOURCE_DATA_LEVEL,
00387                                &ResourceDataEntry);
00388 
00389     /* Make sure it worked */
00390     if (NT_SUCCESS(Status))
00391     {
00392         /* Now actually get a pointer to it */
00393         Status = LdrAccessResource(LdrEntry->DllBase,
00394                                    ResourceDataEntry,
00395                                    (PVOID*)&BugCheckData,
00396                                    NULL);
00397         if (NT_SUCCESS(Status)) KiBugCodeMessages = BugCheckData;
00398     }
00399 }
00400 
00401 BOOLEAN
00402 NTAPI
00403 KeGetBugMessageText(IN ULONG BugCheckCode,
00404                     OUT PANSI_STRING OutputString OPTIONAL)
00405 {
00406     ULONG i, j;
00407     ULONG IdOffset;
00408     ULONG_PTR MessageEntry;
00409     PCHAR BugCode;
00410     BOOLEAN Result = FALSE;
00411     USHORT Length;
00412 
00413     /* Make sure we're not bugchecking too early */
00414     if (!KiBugCodeMessages) return Result;
00415 
00416     /* Find the message. This code is based on RtlFindMesssage */
00417     for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++)
00418     {
00419         /* Check if the ID Matches */
00420         if ((BugCheckCode >= KiBugCodeMessages->Blocks[i].LowId) &&
00421             (BugCheckCode <= KiBugCodeMessages->Blocks[i].HighId))
00422         {
00423             /* Get Offset to Entry */
00424             MessageEntry = KiBugCodeMessages->Blocks[i].OffsetToEntries +
00425                            (ULONG_PTR)KiBugCodeMessages;
00426             IdOffset = BugCheckCode - KiBugCodeMessages->Blocks[i].LowId;
00427 
00428             /* Get offset to ID */
00429             for (j = 0; j < IdOffset; j++)
00430             {
00431                 /* Advance in the Entries */
00432                 MessageEntry += ((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->
00433                                 Length;
00434             }
00435 
00436             /* Get the final Code */
00437             BugCode = (PCHAR)((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
00438             Length = (USHORT)strlen(BugCode);
00439 
00440             /* Handle trailing newlines */
00441             while ((Length > 0) && ((BugCode[Length] == '\n') ||
00442                                     (BugCode[Length] == '\r') ||
00443                                     (BugCode[Length] == ANSI_NULL)))
00444             {
00445                 /* Check if we have a string to return */
00446                 if (!OutputString) BugCode[Length] = ANSI_NULL;
00447                 Length--;
00448             }
00449 
00450             /* Check if caller wants an output string */
00451             if (OutputString)
00452             {
00453                 /* Return it in the OutputString */
00454                 OutputString->Buffer = BugCode;
00455                 OutputString->Length = Length + 1;
00456                 OutputString->MaximumLength = Length + 1;
00457             }
00458             else
00459             {
00460                 /* Direct Output to Screen */
00461                 InbvDisplayString(BugCode);
00462                 InbvDisplayString("\r");
00463             }
00464 
00465             /* We're done */
00466             Result = TRUE;
00467             break;
00468         }
00469     }
00470 
00471     /* Return the result */
00472     return Result;
00473 }
00474 
00475 VOID
00476 NTAPI
00477 KiDoBugCheckCallbacks(VOID)
00478 {
00479     PKBUGCHECK_CALLBACK_RECORD CurrentRecord;
00480     PLIST_ENTRY ListHead, NextEntry, LastEntry;
00481     ULONG_PTR Checksum;
00482 
00483     /* First make sure that the list is Initialized... it might not be */
00484     ListHead = &KeBugcheckCallbackListHead;
00485     if ((ListHead->Flink) && (ListHead->Blink))
00486     {
00487         /* Loop the list */
00488         LastEntry = ListHead;
00489         NextEntry = ListHead->Flink;
00490         while (NextEntry != ListHead)
00491         {
00492             /* Get the reord */
00493             CurrentRecord = CONTAINING_RECORD(NextEntry,
00494                                               KBUGCHECK_CALLBACK_RECORD,
00495                                               Entry);
00496 
00497             /* Validate it */
00498             if (CurrentRecord->Entry.Blink != LastEntry) return;
00499             Checksum = (ULONG_PTR)CurrentRecord->CallbackRoutine;
00500             Checksum += (ULONG_PTR)CurrentRecord->Buffer;
00501             Checksum += (ULONG_PTR)CurrentRecord->Length;
00502             Checksum += (ULONG_PTR)CurrentRecord->Component;
00503 
00504             /* Make sure it's inserted and valitdated */
00505             if ((CurrentRecord->State == BufferInserted) &&
00506                 (CurrentRecord->Checksum == Checksum))
00507             {
00508                 /* Call the routine */
00509                 CurrentRecord->State = BufferStarted;
00510                 (CurrentRecord->CallbackRoutine)(CurrentRecord->Buffer,
00511                                                  CurrentRecord->Length);
00512                 CurrentRecord->State = BufferFinished;
00513             }
00514 
00515             /* Go to the next entry */
00516             LastEntry = NextEntry;
00517             NextEntry = NextEntry->Flink;
00518         }
00519     }
00520 }
00521 
00522 VOID
00523 NTAPI
00524 KiBugCheckDebugBreak(IN ULONG StatusCode)
00525 {
00526     /*
00527      * Wrap this in SEH so we don't crash if
00528      * there is no debugger or if it disconnected
00529      */
00530 DoBreak:
00531     _SEH2_TRY
00532     {
00533         /* Breakpoint */
00534         DbgBreakPointWithStatus(StatusCode);
00535     }
00536     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00537     {
00538         /* No debugger, halt the CPU */
00539         HalHaltSystem();
00540     }
00541     _SEH2_END;
00542 
00543     /* Break again if this wasn't first try */
00544     if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak;
00545 }
00546 
00547 PCHAR
00548 NTAPI
00549 KeBugCheckUnicodeToAnsi(IN PUNICODE_STRING Unicode,
00550                         OUT PCHAR Ansi,
00551                         IN ULONG Length)
00552 {
00553     PCHAR p;
00554     PWCHAR pw;
00555     ULONG i;
00556 
00557     /* Set length and normalize it */
00558     i = Unicode->Length / sizeof(WCHAR);
00559     i = min(i, Length - 1);
00560 
00561     /* Set source and destination, and copy */
00562     pw = Unicode->Buffer;
00563     p = Ansi;
00564     while (i--) *p++ = (CHAR)*pw++;
00565 
00566     /* Null terminate and return */
00567     *p = ANSI_NULL;
00568     return Ansi;
00569 }
00570 
00571 VOID
00572 NTAPI
00573 KiDumpParameterImages(IN PCHAR Message,
00574                       IN PULONG_PTR Parameters,
00575                       IN ULONG ParameterCount,
00576                       IN PKE_BUGCHECK_UNICODE_TO_ANSI ConversionRoutine)
00577 {
00578     ULONG i;
00579     BOOLEAN InSystem;
00580     PLDR_DATA_TABLE_ENTRY LdrEntry;
00581     PVOID ImageBase;
00582     PUNICODE_STRING DriverName;
00583     CHAR AnsiName[32];
00584     PIMAGE_NT_HEADERS NtHeader;
00585     ULONG TimeStamp;
00586     BOOLEAN FirstRun = TRUE;
00587 
00588     /* Loop parameters */
00589     for (i = 0; i < ParameterCount; i++)
00590     {
00591         /* Get the base for this parameter */
00592         ImageBase = KiPcToFileHeader((PVOID)Parameters[i],
00593                                      &LdrEntry,
00594                                      FALSE,
00595                                      &InSystem);
00596         if (!ImageBase)
00597         {
00598             /* FIXME: Add code to check for unloaded drivers */
00599             DPRINT1("Potentially unloaded driver!\n");
00600             continue;
00601         }
00602         else
00603         {
00604             /* Get the NT Headers and Timestamp */
00605             NtHeader = RtlImageNtHeader(LdrEntry->DllBase);
00606             TimeStamp = NtHeader->FileHeader.TimeDateStamp;
00607 
00608             /* Convert the driver name */
00609             DriverName = &LdrEntry->BaseDllName;
00610             ConversionRoutine(&LdrEntry->BaseDllName,
00611                               AnsiName,
00612                               sizeof(AnsiName));
00613         }
00614 
00615         /* Format driver name */
00616         sprintf(Message,
00617                 "%s**  %12s - Address %p base at %p, DateStamp %08lx\n",
00618                 FirstRun ? "\r\n*":"*",
00619                 AnsiName,
00620                 (PVOID)Parameters[i],
00621                 ImageBase,
00622                 TimeStamp);
00623 
00624         /* Check if we only had one parameter */
00625         if (ParameterCount <= 1)
00626         {
00627             /* Then just save the name */
00628             KiBugCheckDriver = DriverName;
00629         }
00630         else
00631         {
00632             /* Otherwise, display the message */
00633             InbvDisplayString(Message);
00634         }
00635 
00636         /* Loop again */
00637         FirstRun = FALSE;
00638     }
00639 }
00640 
00641 VOID
00642 NTAPI
00643 KiDisplayBlueScreen(IN ULONG MessageId,
00644                     IN BOOLEAN IsHardError,
00645                     IN PCHAR HardErrCaption OPTIONAL,
00646                     IN PCHAR HardErrMessage OPTIONAL,
00647                     IN PCHAR Message)
00648 {
00649     CHAR AnsiName[75];
00650 
00651     /* Check if bootvid is installed */
00652     if (InbvIsBootDriverInstalled())
00653     {
00654         /* Acquire ownership and reset the display */
00655         InbvAcquireDisplayOwnership();
00656         InbvResetDisplay();
00657 
00658         /* Display blue screen */
00659         InbvSolidColorFill(0, 0, 639, 479, 4);
00660         InbvSetTextColor(15);
00661         InbvInstallDisplayStringFilter(NULL);
00662         InbvEnableDisplayString(TRUE);
00663         InbvSetScrollRegion(0, 0, 639, 479);
00664     }
00665 
00666     /* Check if this is a hard error */
00667     if (IsHardError)
00668     {
00669         /* Display caption and message */
00670         if (HardErrCaption) InbvDisplayString(HardErrCaption);
00671         if (HardErrMessage) InbvDisplayString(HardErrMessage);
00672     }
00673 
00674     /* Begin the display */
00675     InbvDisplayString("\r\n");
00676 
00677     /* Print out initial message */
00678     KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO, NULL);
00679     InbvDisplayString("\r\n\r\n");
00680 
00681     /* Check if we have a driver */
00682     if (KiBugCheckDriver)
00683     {
00684         /* Print out into to driver name */
00685         KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL);
00686 
00687         /* Convert and print out driver name */
00688         KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName));
00689         InbvDisplayString(" ");
00690         InbvDisplayString(AnsiName);
00691         InbvDisplayString("\r\n\r\n");
00692     }
00693 
00694     /* Check if this is the generic message */
00695     if (MessageId == BUGCODE_PSS_MESSAGE)
00696     {
00697         /* It is, so get the bug code string as well */
00698         KeGetBugMessageText((ULONG)KiBugCheckData[0], NULL);
00699         InbvDisplayString("\r\n\r\n");
00700     }
00701 
00702     /* Print second introduction message */
00703     KeGetBugMessageText(PSS_MESSAGE_INTRO, NULL);
00704     InbvDisplayString("\r\n\r\n");
00705 
00706     /* Get the bug code string */
00707     KeGetBugMessageText(MessageId, NULL);
00708     InbvDisplayString("\r\n\r\n");
00709 
00710     /* Print message for technical information */
00711     KeGetBugMessageText(BUGCHECK_TECH_INFO, NULL);
00712 
00713     /* Show the technical Data */
00714     sprintf(AnsiName,
00715             "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
00716             KiBugCheckData[0],
00717             (PVOID)KiBugCheckData[1],
00718             (PVOID)KiBugCheckData[2],
00719             (PVOID)KiBugCheckData[3],
00720             (PVOID)KiBugCheckData[4]);
00721     InbvDisplayString(AnsiName);
00722 
00723     /* Check if we have a driver*/
00724     if (KiBugCheckDriver)
00725     {
00726         /* Display technical driver data */
00727         InbvDisplayString(Message);
00728     }
00729     else
00730     {
00731         /* Dump parameter information */
00732         KiDumpParameterImages(Message,
00733                               (PVOID)&KiBugCheckData[1],
00734                               4,
00735                               KeBugCheckUnicodeToAnsi);
00736     }
00737 }
00738 
00739 VOID
00740 NTAPI
00741 KeBugCheckWithTf(IN ULONG BugCheckCode,
00742                  IN ULONG_PTR BugCheckParameter1,
00743                  IN ULONG_PTR BugCheckParameter2,
00744                  IN ULONG_PTR BugCheckParameter3,
00745                  IN ULONG_PTR BugCheckParameter4,
00746                  IN PKTRAP_FRAME TrapFrame)
00747 {
00748     PKPRCB Prcb = KeGetCurrentPrcb();
00749     CONTEXT Context;
00750     ULONG MessageId;
00751     CHAR AnsiName[128];
00752     BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE;
00753     PCHAR HardErrCaption = NULL, HardErrMessage = NULL;
00754     PVOID Pc = NULL, Memory;
00755     PVOID DriverBase;
00756     PLDR_DATA_TABLE_ENTRY LdrEntry;
00757     PULONG_PTR HardErrorParameters;
00758     KIRQL OldIrql;
00759 #ifdef CONFIG_SMP
00760     LONG i = 0;
00761 #endif
00762 
00763     /* Set active bugcheck */
00764     KeBugCheckActive = TRUE;
00765     KiBugCheckDriver = NULL;
00766 
00767     /* Check if this is power failure simulation */
00768     if (BugCheckCode == POWER_FAILURE_SIMULATE)
00769     {
00770         /* Call the Callbacks and reboot */
00771         KiDoBugCheckCallbacks();
00772         HalReturnToFirmware(HalRebootRoutine);
00773     }
00774 
00775     /* Save the IRQL and set hardware trigger */
00776     Prcb->DebuggerSavedIRQL = KeGetCurrentIrql();
00777     InterlockedIncrement((PLONG)&KiHardwareTrigger);
00778 
00779     /* Capture the CPU Context */
00780     RtlCaptureContext(&Prcb->ProcessorState.ContextFrame);
00781     KiSaveProcessorControlState(&Prcb->ProcessorState);
00782     Context = Prcb->ProcessorState.ContextFrame;
00783 
00784     /* FIXME: Call the Watchdog if it's registered */
00785 
00786     /* Check which bugcode this is */
00787     switch (BugCheckCode)
00788     {
00789         /* These bug checks already have detailed messages, keep them */
00790         case UNEXPECTED_KERNEL_MODE_TRAP:
00791         case DRIVER_CORRUPTED_EXPOOL:
00792         case ACPI_BIOS_ERROR:
00793         case ACPI_BIOS_FATAL_ERROR:
00794         case THREAD_STUCK_IN_DEVICE_DRIVER:
00795         case DATA_BUS_ERROR:
00796         case FAT_FILE_SYSTEM:
00797         case NO_MORE_SYSTEM_PTES:
00798         case INACCESSIBLE_BOOT_DEVICE:
00799 
00800             /* Keep the same code */
00801             MessageId = BugCheckCode;
00802             break;
00803 
00804         /* Check if this is a kernel-mode exception */
00805         case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
00806         case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
00807         case KMODE_EXCEPTION_NOT_HANDLED:
00808 
00809             /* Use the generic text message */
00810             MessageId = KMODE_EXCEPTION_NOT_HANDLED;
00811             break;
00812 
00813         /* File-system errors */
00814         case NTFS_FILE_SYSTEM:
00815 
00816             /* Use the generic message for FAT */
00817             MessageId = FAT_FILE_SYSTEM;
00818             break;
00819 
00820         /* Check if this is a coruption of the Mm's Pool */
00821         case DRIVER_CORRUPTED_MMPOOL:
00822 
00823             /* Use generic corruption message */
00824             MessageId = DRIVER_CORRUPTED_EXPOOL;
00825             break;
00826 
00827         /* Check if this is a signature check failure */
00828         case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE:
00829 
00830             /* Use the generic corruption message */
00831             MessageId = BUGCODE_PSS_MESSAGE_SIGNATURE;
00832             break;
00833 
00834         /* All other codes */
00835         default:
00836 
00837             /* Use the default bugcheck message */
00838             MessageId = BUGCODE_PSS_MESSAGE;
00839             break;
00840     }
00841 
00842     /* Save bugcheck data */
00843     KiBugCheckData[0] = BugCheckCode;
00844     KiBugCheckData[1] = BugCheckParameter1;
00845     KiBugCheckData[2] = BugCheckParameter2;
00846     KiBugCheckData[3] = BugCheckParameter3;
00847     KiBugCheckData[4] = BugCheckParameter4;
00848 
00849     /* Now check what bugcheck this is */
00850     switch (BugCheckCode)
00851     {
00852         /* Invalid access to R/O memory or Unhandled KM Exception */
00853         case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
00854         case ATTEMPTED_WRITE_TO_READONLY_MEMORY:
00855         case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY:
00856 
00857             /* Check if we have a trap frame */
00858             if (!TrapFrame)
00859             {
00860                 /* Use parameter 3 as a trap frame, if it exists */
00861                 if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
00862             }
00863 
00864             /* Check if we got one now and if we need to get the Program Counter */
00865             if ((TrapFrame) &&
00866                 (BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED))
00867             {
00868                 /* Get the Program Counter */
00869                 Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
00870             }
00871             break;
00872 
00873         /* Wrong IRQL */
00874         case IRQL_NOT_LESS_OR_EQUAL:
00875 
00876             /*
00877              * The NT kernel has 3 special sections:
00878              * MISYSPTE, POOLMI and POOLCODE. The bug check code can
00879              * determine in which of these sections this bugcode happened
00880              * and provide a more detailed analysis. For now, we don't.
00881              */
00882 
00883             /* Program Counter is in parameter 4 */
00884             Pc = (PVOID)BugCheckParameter4;
00885 
00886             /* Get the driver base */
00887             DriverBase = KiPcToFileHeader(Pc,
00888                                           &LdrEntry,
00889                                           FALSE,
00890                                           &IsSystem);
00891             if (IsSystem)
00892             {
00893                 /*
00894                  * The error happened inside the kernel or HAL.
00895                  * Get the memory address that was being referenced.
00896                  */
00897                 Memory = (PVOID)BugCheckParameter1;
00898 
00899                 /* Find to which driver it belongs */
00900                 DriverBase = KiPcToFileHeader(Memory,
00901                                               &LdrEntry,
00902                                               TRUE,
00903                                               &IsSystem);
00904                 if (DriverBase)
00905                 {
00906                     /* Get the driver name and update the bug code */
00907                     KiBugCheckDriver = &LdrEntry->BaseDllName;
00908                     KiBugCheckData[0] = DRIVER_PORTION_MUST_BE_NONPAGED;
00909                 }
00910                 else
00911                 {
00912                     /* Find the driver that unloaded at this address */
00913                     KiBugCheckDriver = NULL; // FIXME: ROS can't locate
00914 
00915                     /* Check if the cause was an unloaded driver */
00916                     if (KiBugCheckDriver)
00917                     {
00918                         /* Update bug check code */
00919                         KiBugCheckData[0] =
00920                             SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD;
00921                     }
00922                 }
00923             }
00924             else
00925             {
00926                 /* Update the bug check code */
00927                 KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
00928             }
00929 
00930             /* Clear Pc so we don't look it up later */
00931             Pc = NULL;
00932             break;
00933 
00934         /* Hard error */
00935         case FATAL_UNHANDLED_HARD_ERROR:
00936 
00937             /* Copy bug check data from hard error */
00938             HardErrorParameters = (PULONG_PTR)BugCheckParameter2;
00939             KiBugCheckData[0] = BugCheckParameter1;
00940             KiBugCheckData[1] = HardErrorParameters[0];
00941             KiBugCheckData[2] = HardErrorParameters[1];
00942             KiBugCheckData[3] = HardErrorParameters[2];
00943             KiBugCheckData[4] = HardErrorParameters[3];
00944 
00945             /* Remember that this is hard error and set the caption/message */
00946             IsHardError = TRUE;
00947             HardErrCaption = (PCHAR)BugCheckParameter3;
00948             HardErrMessage = (PCHAR)BugCheckParameter4;
00949             break;
00950 
00951         /* Page fault */
00952         case PAGE_FAULT_IN_NONPAGED_AREA:
00953 
00954             /* Assume no driver */
00955             DriverBase = NULL;
00956 
00957             /* Check if we have a trap frame */
00958             if (!TrapFrame)
00959             {
00960                 /* We don't, use parameter 3 if possible */
00961                 if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
00962             }
00963 
00964             /* Check if we have a frame now */
00965             if (TrapFrame)
00966             {
00967                 /* Get the Program Counter */
00968                 Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
00969                 KiBugCheckData[3] = (ULONG_PTR)Pc;
00970 
00971                 /* Find out if was in the kernel or drivers */
00972                 DriverBase = KiPcToFileHeader(Pc,
00973                                               &LdrEntry,
00974                                               FALSE,
00975                                               &IsSystem);
00976             }
00977 
00978             /*
00979              * Now we should check if this happened in:
00980              * 1) Special Pool 2) Free Special Pool 3) Session Pool
00981              * and update the bugcheck code appropriately.
00982              */
00983 
00984             /* Check if we didn't have a driver base */
00985             if (!DriverBase)
00986             {
00987                 /* Find the driver that unloaded at this address */
00988                 KiBugCheckDriver = NULL; // FIXME: ROS can't locate
00989 
00990                 /* Check if the cause was an unloaded driver */
00991                 if (KiBugCheckDriver)
00992                 {
00993                     KiBugCheckData[0] =
00994                         DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS;
00995                 }
00996             }
00997             break;
00998 
00999         /* Check if the driver forgot to unlock pages */
01000         case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
01001 
01002             /* Program Counter is in parameter 1 */
01003             Pc = (PVOID)BugCheckParameter1;
01004             break;
01005 
01006         /* Check if the driver consumed too many PTEs */
01007         case DRIVER_USED_EXCESSIVE_PTES:
01008 
01009             /* Loader entry is in parameter 1 */
01010             LdrEntry = (PVOID)BugCheckParameter1;
01011             KiBugCheckDriver = &LdrEntry->BaseDllName;
01012             break;
01013 
01014         /* Check if the driver has a stuck thread */
01015         case THREAD_STUCK_IN_DEVICE_DRIVER:
01016 
01017             /* The name is in Parameter 3 */
01018             KiBugCheckDriver = (PVOID)BugCheckParameter3;
01019             break;
01020 
01021         /* Anything else */
01022         default:
01023             break;
01024     }
01025 
01026     /* Do we have a driver name? */
01027     if (KiBugCheckDriver)
01028     {
01029         /* Convert it to ANSI */
01030         KeBugCheckUnicodeToAnsi(KiBugCheckDriver, AnsiName, sizeof(AnsiName));
01031     }
01032     else
01033     {
01034         /* Do we have a Program Counter? */
01035         if (Pc)
01036         {
01037             /* Dump image name */
01038             KiDumpParameterImages(AnsiName,
01039                                   (PULONG_PTR)&Pc,
01040                                   1,
01041                                   KeBugCheckUnicodeToAnsi);
01042         }
01043     }
01044 
01045     /* Check if we need to save the context for KD */
01046 #ifdef _WINKD_
01047     if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG_PTR)&Context;
01048 #endif
01049 
01050     /* Check if a debugger is connected */
01051     if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled))
01052     {
01053         /* Crash on the debugger console */
01054         DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
01055                  "                       (0x%p,0x%p,0x%p,0x%p)\n\n",
01056                  KiBugCheckData[0],
01057                  KiBugCheckData[1],
01058                  KiBugCheckData[2],
01059                  KiBugCheckData[3],
01060                  KiBugCheckData[4]);
01061 
01062         /* Check if the debugger isn't currently connected */
01063         if (!KdDebuggerNotPresent)
01064         {
01065             /* Check if we have a driver to blame */
01066             if (KiBugCheckDriver)
01067             {
01068                 /* Dump it */
01069                 DbgPrint("Driver at fault: %s.\n", AnsiName);
01070             }
01071 
01072             /* Check if this was a hard error */
01073             if (IsHardError)
01074             {
01075                 /* Print caption and message */
01076                 if (HardErrCaption) DbgPrint(HardErrCaption);
01077                 if (HardErrMessage) DbgPrint(HardErrMessage);
01078             }
01079 
01080             /* Break in the debugger */
01081             KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_FIRST);
01082         }
01083         else
01084         {
01085             /*
01086              * ROS HACK.
01087              * Ok, so debugging is enabled, but KDBG isn't there.
01088              * We'll manually dump the stack for the user.
01089              */
01090             KeRosDumpStackFrames(NULL, 0);
01091 
01092             /* ROS HACK 2: Generate something useful for Bugzilla */
01093             KeRosDumpTriageForBugZillaReport();
01094         }
01095     }
01096 
01097     /* Raise IRQL to HIGH_LEVEL */
01098     _disable();
01099     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
01100 
01101     /* Avoid recursion */
01102     if (!InterlockedDecrement((PLONG)&KeBugCheckCount))
01103     {
01104 #ifdef CONFIG_SMP
01105         /* Set CPU that is bug checking now */
01106         KeBugCheckOwner = Prcb->Number;
01107 
01108         /* Freeze the other CPUs */
01109         for (i = 0; i < KeNumberProcessors; i++)
01110         {
01111             if (i != (LONG)KeGetCurrentProcessorNumber())
01112             {
01113                 /* Send the IPI and give them one second to catch up */
01114                 KiIpiSend(1 << i, IPI_FREEZE);
01115                 KeStallExecutionProcessor(1000000);
01116             }
01117         }
01118 #endif
01119 
01120         /* Display the BSOD */
01121         KiDisplayBlueScreen(MessageId,
01122                             IsHardError,
01123                             HardErrCaption,
01124                             HardErrMessage,
01125                             AnsiName);
01126 
01127         /* Check if the debugger is disabled but we can enable it */
01128         if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
01129         {
01130             /* Enable it */
01131 #ifdef _WINKD_
01132             KdEnableDebuggerWithLock(FALSE);
01133 #endif
01134         }
01135         else
01136         {
01137             /* Otherwise, print the last line */
01138             InbvDisplayString("\r\n");
01139         }
01140 
01141         /* Save the context */
01142         Prcb->ProcessorState.ContextFrame = Context;
01143 
01144         /* FIXME: Support Triage Dump */
01145 
01146         /* FIXME: Write the crash dump */
01147     }
01148     else
01149     {
01150         /* Increase recursion count */
01151         KeBugCheckOwnerRecursionCount++;
01152         if (KeBugCheckOwnerRecursionCount == 2)
01153         {
01154             /* Break in the debugger */
01155             KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
01156         }
01157         else if (KeBugCheckOwnerRecursionCount > 2)
01158         {
01159             /* Halt execution */
01160             while (TRUE);
01161         }
01162     }
01163 
01164     /* Call the Callbacks */
01165     KiDoBugCheckCallbacks();
01166 
01167     /* FIXME: Call Watchdog if enabled */
01168 
01169     /* Check if we have to reboot */
01170     if (Reboot)
01171     {
01172         /* Unload symbols */
01173         DbgUnLoadImageSymbols(NULL, (PVOID)MAXULONG_PTR, 0);
01174         HalReturnToFirmware(HalRebootRoutine);
01175     }
01176 
01177     /* Attempt to break in the debugger (otherwise halt CPU) */
01178     KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
01179 
01180     /* Shouldn't get here */
01181     while (TRUE);
01182 }
01183 
01184 BOOLEAN
01185 NTAPI
01186 KiHandleNmi(VOID)
01187 {
01188     BOOLEAN Handled = FALSE;
01189     PKNMI_HANDLER_CALLBACK NmiData;
01190 
01191     /* Parse the list of callbacks */
01192     NmiData = KiNmiCallbackListHead;
01193     while (NmiData)
01194     {
01195         /* Save if this callback has handled it -- all it takes is one */
01196         Handled |= NmiData->Callback(NmiData->Context, Handled);
01197         NmiData = NmiData->Next;
01198     }
01199 
01200     /* Has anyone handled this? */
01201     return Handled;
01202 }
01203 
01204 /* PUBLIC FUNCTIONS **********************************************************/
01205 
01206 /*
01207  * @unimplemented
01208  */
01209 NTSTATUS
01210 NTAPI
01211 KeInitializeCrashDumpHeader(IN ULONG Type,
01212                             IN ULONG Flags,
01213                             OUT PVOID Buffer,
01214                             IN ULONG BufferSize,
01215                             OUT ULONG BufferNeeded OPTIONAL)
01216 {
01217     UNIMPLEMENTED;
01218     return STATUS_UNSUCCESSFUL;
01219 }
01220 
01221 /*
01222  * @implemented
01223  */
01224 BOOLEAN
01225 NTAPI
01226 KeDeregisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
01227 {
01228     KIRQL OldIrql;
01229     BOOLEAN Status = FALSE;
01230 
01231     /* Raise IRQL to High */
01232     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
01233 
01234     /* Check the Current State */
01235     if (CallbackRecord->State == BufferInserted)
01236     {
01237         /* Reset state and remove from list */
01238         CallbackRecord->State = BufferEmpty;
01239         RemoveEntryList(&CallbackRecord->Entry);
01240         Status = TRUE;
01241     }
01242 
01243     /* Lower IRQL and return */
01244     KeLowerIrql(OldIrql);
01245     return Status;
01246 }
01247 
01248 /*
01249  * @implemented
01250  */
01251 BOOLEAN
01252 NTAPI
01253 KeDeregisterBugCheckReasonCallback(
01254     IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
01255 {
01256     KIRQL OldIrql;
01257     BOOLEAN Status = FALSE;
01258 
01259     /* Raise IRQL to High */
01260     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
01261 
01262     /* Check the Current State */
01263     if (CallbackRecord->State == BufferInserted)
01264     {
01265         /* Reset state and remove from list */
01266         CallbackRecord->State = BufferEmpty;
01267         RemoveEntryList(&CallbackRecord->Entry);
01268         Status = TRUE;
01269     }
01270 
01271     /* Lower IRQL and return */
01272     KeLowerIrql(OldIrql);
01273     return Status;
01274 }
01275 
01276 /*
01277  * @implemented
01278  */
01279 BOOLEAN
01280 NTAPI
01281 KeRegisterBugCheckCallback(IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
01282                            IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
01283                            IN PVOID Buffer,
01284                            IN ULONG Length,
01285                            IN PUCHAR Component)
01286 {
01287     KIRQL OldIrql;
01288     BOOLEAN Status = FALSE;
01289 
01290     /* Raise IRQL to High */
01291     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
01292 
01293     /* Check the Current State first so we don't double-register */
01294     if (CallbackRecord->State == BufferEmpty)
01295     {
01296         /* Set the Callback Settings and insert into the list */
01297         CallbackRecord->Length = Length;
01298         CallbackRecord->Buffer = Buffer;
01299         CallbackRecord->Component = Component;
01300         CallbackRecord->CallbackRoutine = CallbackRoutine;
01301         CallbackRecord->State = BufferInserted;
01302         InsertTailList(&KeBugcheckCallbackListHead, &CallbackRecord->Entry);
01303         Status = TRUE;
01304     }
01305 
01306     /* Lower IRQL and return */
01307     KeLowerIrql(OldIrql);
01308     return Status;
01309 }
01310 
01311 /*
01312  * @implemented
01313  */
01314 BOOLEAN
01315 NTAPI
01316 KeRegisterBugCheckReasonCallback(
01317     IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
01318     IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
01319     IN KBUGCHECK_CALLBACK_REASON Reason,
01320     IN PUCHAR Component)
01321 {
01322     KIRQL OldIrql;
01323     BOOLEAN Status = FALSE;
01324 
01325     /* Raise IRQL to High */
01326     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
01327 
01328     /* Check the Current State first so we don't double-register */
01329     if (CallbackRecord->State == BufferEmpty)
01330     {
01331         /* Set the Callback Settings and insert into the list */
01332         CallbackRecord->Component = Component;
01333         CallbackRecord->CallbackRoutine = CallbackRoutine;
01334         CallbackRecord->State = BufferInserted;
01335         CallbackRecord->Reason = Reason;
01336         InsertTailList(&KeBugcheckReasonCallbackListHead,
01337                        &CallbackRecord->Entry);
01338         Status = TRUE;
01339     }
01340 
01341     /* Lower IRQL and return */
01342     KeLowerIrql(OldIrql);
01343     return Status;
01344 }
01345 
01346 /*
01347  * @implemented
01348  */
01349 PVOID
01350 NTAPI
01351 KeRegisterNmiCallback(IN PNMI_CALLBACK CallbackRoutine,
01352                       IN PVOID Context)
01353 {
01354     KIRQL OldIrql;
01355     PKNMI_HANDLER_CALLBACK NmiData, Next;
01356     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
01357 
01358     /* Allocate NMI callback data */
01359     NmiData = ExAllocatePoolWithTag(NonPagedPool,
01360                                     sizeof(KNMI_HANDLER_CALLBACK),
01361                                     'IMNK');
01362     if (!NmiData) return NULL;
01363 
01364     /* Fill in the information */
01365     NmiData->Callback = CallbackRoutine;
01366     NmiData->Context = Context;
01367     NmiData->Handle = NmiData;
01368 
01369     /* Insert it into NMI callback list */
01370     KiAcquireNmiListLock(&OldIrql);
01371     NmiData->Next = KiNmiCallbackListHead;
01372     Next = InterlockedCompareExchangePointer((PVOID*)&KiNmiCallbackListHead,
01373                                              NmiData,
01374                                              NmiData->Next);
01375     ASSERT(Next == NmiData->Next);
01376     KiReleaseNmiListLock(OldIrql);
01377 
01378     /* Return the opaque "handle" */
01379     return NmiData->Handle;
01380 }
01381 
01382 /*
01383  * @implemented
01384  */
01385 NTSTATUS
01386 NTAPI
01387 KeDeregisterNmiCallback(PVOID Handle)
01388 {
01389     UNIMPLEMENTED;
01390     return STATUS_UNSUCCESSFUL;
01391 }
01392 
01393 /*
01394  * @implemented
01395  */
01396 VOID
01397 NTAPI
01398 KeBugCheckEx(IN ULONG BugCheckCode,
01399              IN ULONG_PTR BugCheckParameter1,
01400              IN ULONG_PTR BugCheckParameter2,
01401              IN ULONG_PTR BugCheckParameter3,
01402              IN ULONG_PTR BugCheckParameter4)
01403 {
01404     /* Call the internal API */
01405     KeBugCheckWithTf(BugCheckCode,
01406                      BugCheckParameter1,
01407                      BugCheckParameter2,
01408                      BugCheckParameter3,
01409                      BugCheckParameter4,
01410                      NULL);
01411 }
01412 
01413 /*
01414  * @implemented
01415  */
01416 VOID
01417 NTAPI
01418 KeBugCheck(ULONG BugCheckCode)
01419 {
01420     /* Call the internal API */
01421     KeBugCheckWithTf(BugCheckCode, 0, 0, 0, 0, NULL);
01422 }
01423 
01424 /*
01425  * @implemented
01426  */
01427 VOID
01428 NTAPI
01429 KeEnterKernelDebugger(VOID)
01430 {
01431     /* Disable interrupts */
01432     KiHardwareTrigger = 1;
01433     _disable();
01434 
01435     /* Check the bugcheck count */
01436     if (!InterlockedDecrement((PLONG)&KeBugCheckCount))
01437     {
01438         /* There was only one, is the debugger disabled? */
01439         if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
01440         {
01441             /* Enable the debugger */
01442             KdInitSystem(0, NULL);
01443         }
01444     }
01445 
01446     /* Break in the debugger */
01447     KiBugCheckDebugBreak(DBG_STATUS_FATAL);
01448 }
01449 
01450 /* EOF */

Generated on Fri May 25 2012 04:35:54 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.