Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2007 lines
56 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. stubs.c
  5. Abstract:
  6. This module implements bug check and system shutdown code.
  7. Author:
  8. Mark Lucovsky (markl) 30-Aug-1990
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #define NOEXTAPI
  15. #include "wdbgexts.h"
  16. #include <inbv.h>
  17. #include <hdlsblk.h>
  18. #include <hdlsterm.h>
  19. //
  20. //
  21. //
  22. extern KDDEBUGGER_DATA64 KdDebuggerDataBlock;
  23. extern PVOID ExPoolCodeStart;
  24. extern PVOID ExPoolCodeEnd;
  25. extern PVOID MmPoolCodeStart;
  26. extern PVOID MmPoolCodeEnd;
  27. extern PVOID MmPteCodeStart;
  28. extern PVOID MmPteCodeEnd;
  29. extern PWD_HANDLER ExpWdHandler;
  30. extern PVOID ExpWdHandlerContext;
  31. #if defined(_AMD64_)
  32. #define PROGRAM_COUNTER(_trapframe) ((_trapframe)->Rip)
  33. #elif defined(_X86_)
  34. #define PROGRAM_COUNTER(_trapframe) ((_trapframe)->Eip)
  35. #elif defined(_IA64_)
  36. #define PROGRAM_COUNTER(_trapframe) ((_trapframe)->StIIP)
  37. #else
  38. #error "no target architecture"
  39. #endif
  40. //
  41. // Define forward referenced prototypes.
  42. //
  43. VOID
  44. KiScanBugCheckCallbackList (
  45. VOID
  46. );
  47. VOID
  48. KiInvokeBugCheckEntryCallbacks (
  49. VOID
  50. );
  51. //
  52. // Define bug count recursion counter and a context buffer.
  53. //
  54. LONG KeBugCheckCount = 1;
  55. VOID
  56. KeBugCheck (
  57. IN ULONG BugCheckCode
  58. )
  59. {
  60. KeBugCheck2(BugCheckCode,0,0,0,0,NULL);
  61. }
  62. VOID
  63. KeBugCheckEx (
  64. IN ULONG BugCheckCode,
  65. IN ULONG_PTR P1,
  66. IN ULONG_PTR P2,
  67. IN ULONG_PTR P3,
  68. IN ULONG_PTR P4
  69. )
  70. {
  71. KeBugCheck2(BugCheckCode,P1,P2,P3,P4,NULL);
  72. }
  73. ULONG_PTR KiBugCheckData[5];
  74. PUNICODE_STRING KiBugCheckDriver;
  75. BOOLEAN
  76. KeGetBugMessageText(
  77. IN ULONG MessageId,
  78. IN PANSI_STRING ReturnedString OPTIONAL
  79. )
  80. {
  81. SIZE_T i;
  82. PCHAR s;
  83. PMESSAGE_RESOURCE_BLOCK MessageBlock;
  84. PCHAR Buffer;
  85. BOOLEAN Result;
  86. Result = FALSE;
  87. try {
  88. if (KiBugCodeMessages != NULL) {
  89. MmMakeKernelResourceSectionWritable ();
  90. MessageBlock = &KiBugCodeMessages->Blocks[0];
  91. for (i = KiBugCodeMessages->NumberOfBlocks; i; i -= 1) {
  92. if (MessageId >= MessageBlock->LowId &&
  93. MessageId <= MessageBlock->HighId) {
  94. s = (PCHAR)KiBugCodeMessages + MessageBlock->OffsetToEntries;
  95. for (i = MessageId - MessageBlock->LowId; i; i -= 1) {
  96. s += ((PMESSAGE_RESOURCE_ENTRY)s)->Length;
  97. }
  98. Buffer = (PCHAR)((PMESSAGE_RESOURCE_ENTRY)s)->Text;
  99. i = strlen(Buffer) - 1;
  100. while (i > 0 && (Buffer[i] == '\n' ||
  101. Buffer[i] == '\r' ||
  102. Buffer[i] == 0
  103. )
  104. ) {
  105. if (!ARGUMENT_PRESENT( ReturnedString )) {
  106. Buffer[i] = 0;
  107. }
  108. i -= 1;
  109. }
  110. if (!ARGUMENT_PRESENT( ReturnedString )) {
  111. InbvDisplayString((PUCHAR)Buffer);
  112. InbvDisplayString((PUCHAR)"\r");
  113. }
  114. else {
  115. ReturnedString->Buffer = Buffer;
  116. ReturnedString->Length = (USHORT)(i+1);
  117. ReturnedString->MaximumLength = (USHORT)(i+1);
  118. }
  119. Result = TRUE;
  120. break;
  121. }
  122. MessageBlock += 1;
  123. }
  124. }
  125. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  126. ;
  127. }
  128. return Result;
  129. }
  130. PCHAR
  131. KeBugCheckUnicodeToAnsi(
  132. IN PUNICODE_STRING UnicodeString,
  133. OUT PCHAR AnsiBuffer,
  134. IN ULONG MaxAnsiLength
  135. )
  136. {
  137. PCHAR Dst;
  138. PWSTR Src;
  139. ULONG Length;
  140. Length = UnicodeString->Length / sizeof( WCHAR );
  141. if (Length >= MaxAnsiLength) {
  142. Length = MaxAnsiLength - 1;
  143. }
  144. Src = UnicodeString->Buffer;
  145. Dst = AnsiBuffer;
  146. while (Length--) {
  147. *Dst++ = (UCHAR)*Src++;
  148. }
  149. *Dst = '\0';
  150. return AnsiBuffer;
  151. }
  152. VOID
  153. KiBugCheckDebugBreak (
  154. IN ULONG BreakStatus
  155. )
  156. {
  157. do {
  158. try {
  159. //
  160. // Issue a breakpoint
  161. //
  162. DbgBreakPointWithStatus (BreakStatus);
  163. } except(EXCEPTION_EXECUTE_HANDLER) {
  164. HEADLESS_RSP_QUERY_INFO Response;
  165. NTSTATUS Status;
  166. SIZE_T Length;
  167. //
  168. // Failed to issue the breakpoint, must be no debugger. Now, give
  169. // the headless terminal a chance to reboot the system, if there is one.
  170. //
  171. Length = sizeof(HEADLESS_RSP_QUERY_INFO);
  172. Status = HeadlessDispatch(HeadlessCmdQueryInformation,
  173. NULL,
  174. 0,
  175. &Response,
  176. &Length
  177. );
  178. if (NT_SUCCESS(Status) &&
  179. (Response.PortType == HeadlessSerialPort) &&
  180. Response.Serial.TerminalAttached) {
  181. HeadlessDispatch(HeadlessCmdPutString,
  182. "\r\n",
  183. sizeof("\r\n"),
  184. NULL,
  185. NULL
  186. );
  187. for (;;) {
  188. HeadlessDispatch(HeadlessCmdDoBugCheckProcessing, NULL, 0, NULL, NULL);
  189. }
  190. }
  191. //
  192. // No terminal, or it failed, halt the system
  193. //
  194. try {
  195. HalHaltSystem();
  196. } except(EXCEPTION_EXECUTE_HANDLER) {
  197. for (;;) {
  198. }
  199. }
  200. }
  201. } while (BreakStatus != DBG_STATUS_BUGCHECK_FIRST);
  202. }
  203. PVOID
  204. KiPcToFileHeader(
  205. IN PVOID PcValue,
  206. OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry,
  207. IN LOGICAL DriversOnly,
  208. OUT PBOOLEAN InKernelOrHal
  209. )
  210. /*++
  211. Routine Description:
  212. This function returns the base of an image that contains the
  213. specified PcValue. An image contains the PcValue if the PcValue
  214. is within the ImageBase, and the ImageBase plus the size of the
  215. virtual image.
  216. Arguments:
  217. PcValue - Supplies a PcValue.
  218. DataTableEntry - Supplies a pointer to a variable that receives the
  219. address of the data table entry that describes the image.
  220. DriversOnly - Supplies TRUE if the kernel and HAL should be skipped.
  221. InKernelOrHal - Set to TRUE if the PcValue is in the kernel or the HAL.
  222. This only has meaning if DriversOnly is FALSE.
  223. Return Value:
  224. NULL - No image was found that contains the PcValue.
  225. NON-NULL - Returns the base address of the image that contains the
  226. PcValue.
  227. --*/
  228. {
  229. ULONG i;
  230. PLIST_ENTRY ModuleListHead;
  231. PLDR_DATA_TABLE_ENTRY Entry;
  232. PLIST_ENTRY Next;
  233. ULONG_PTR Bounds;
  234. PVOID ReturnBase, Base;
  235. //
  236. // If the module list has been initialized, then scan the list to
  237. // locate the appropriate entry.
  238. //
  239. if (KeLoaderBlock != NULL) {
  240. ModuleListHead = &KeLoaderBlock->LoadOrderListHead;
  241. } else {
  242. ModuleListHead = &PsLoadedModuleList;
  243. }
  244. *InKernelOrHal = FALSE;
  245. ReturnBase = NULL;
  246. Next = ModuleListHead->Flink;
  247. if (Next != NULL) {
  248. i = 0;
  249. while (Next != ModuleListHead) {
  250. if (MmIsAddressValid(Next) == FALSE) {
  251. return NULL;
  252. }
  253. i += 1;
  254. if ((i <= 2) && (DriversOnly == TRUE)) {
  255. Next = Next->Flink;
  256. continue;
  257. }
  258. Entry = CONTAINING_RECORD(Next,
  259. LDR_DATA_TABLE_ENTRY,
  260. InLoadOrderLinks);
  261. Next = Next->Flink;
  262. Base = Entry->DllBase;
  263. Bounds = (ULONG_PTR)Base + Entry->SizeOfImage;
  264. if ((ULONG_PTR)PcValue >= (ULONG_PTR)Base && (ULONG_PTR)PcValue < Bounds) {
  265. *DataTableEntry = Entry;
  266. ReturnBase = Base;
  267. if (i <= 2) {
  268. *InKernelOrHal = TRUE;
  269. }
  270. break;
  271. }
  272. }
  273. }
  274. return ReturnBase;
  275. }
  276. VOID
  277. KiDumpParameterImages(
  278. IN PCHAR Buffer,
  279. IN PULONG_PTR BugCheckParameters,
  280. IN ULONG NumberOfParameters,
  281. IN PKE_BUGCHECK_UNICODE_TO_ANSI UnicodeToAnsiRoutine
  282. )
  283. /*++
  284. Routine Description:
  285. This function formats and displays the image names of boogcheck parameters
  286. that happen to match an address in an image.
  287. Arguments:
  288. Buffer - Supplies a pointer to a buffer to be used to output machine
  289. state information.
  290. BugCheckParameters - Supplies additional bugcheck information.
  291. NumberOfParameters - sizeof BugCheckParameters array.
  292. if just 1 parameter is passed in, just save the string.
  293. UnicodeToAnsiRoutine - Supplies a pointer to a routine to convert Unicode
  294. strings to Ansi strings without touching paged translation tables.
  295. Return Value:
  296. None.
  297. --*/
  298. {
  299. PUNICODE_STRING BugCheckDriver;
  300. ULONG i;
  301. PLDR_DATA_TABLE_ENTRY DataTableEntry;
  302. PVOID ImageBase;
  303. CHAR AnsiBuffer[ 32 ];
  304. ULONG DateStamp;
  305. PIMAGE_NT_HEADERS NtHeaders;
  306. BOOLEAN FirstPrint = TRUE;
  307. BOOLEAN InKernelOrHal;
  308. PUNICODE_STRING DriverName;
  309. //
  310. // At this point the context record contains the machine state at the
  311. // call to bug check.
  312. //
  313. // Put out the system version and the title line with the PSR and FSR.
  314. //
  315. //
  316. // Check to see if any BugCheckParameters are valid code addresses.
  317. // If so, print them for the user.
  318. //
  319. DriverName = NULL;
  320. for (i = 0; i < NumberOfParameters; i += 1) {
  321. DateStamp = 0;
  322. ImageBase = KiPcToFileHeader((PVOID) BugCheckParameters[i],
  323. &DataTableEntry,
  324. TRUE,
  325. &InKernelOrHal);
  326. if (ImageBase == NULL) {
  327. BugCheckDriver = MmLocateUnloadedDriver ((PVOID)BugCheckParameters[i]);
  328. if (BugCheckDriver == NULL){
  329. continue;
  330. }
  331. DriverName = BugCheckDriver;
  332. ImageBase = (PVOID)BugCheckParameters[i];
  333. (*UnicodeToAnsiRoutine) (BugCheckDriver,
  334. AnsiBuffer,
  335. sizeof (AnsiBuffer));
  336. } else {
  337. if (MmIsAddressValid(DataTableEntry->DllBase) == TRUE) {
  338. NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase);
  339. if (NtHeaders) {
  340. DateStamp = NtHeaders->FileHeader.TimeDateStamp;
  341. }
  342. }
  343. DriverName = &DataTableEntry->BaseDllName;
  344. (*UnicodeToAnsiRoutine)( DriverName,
  345. AnsiBuffer,
  346. sizeof( AnsiBuffer ));
  347. }
  348. sprintf(Buffer, "%s** %12s - Address %p base at %p, DateStamp %08lx\r\n",
  349. FirstPrint ? "\r\n*":"*",
  350. AnsiBuffer,
  351. (PVOID)BugCheckParameters[i],
  352. ImageBase,
  353. DateStamp);
  354. //
  355. // Only print the string if we are called to print multiple.
  356. //
  357. if (NumberOfParameters > 1) {
  358. InbvDisplayString((PUCHAR)Buffer);
  359. } else {
  360. KiBugCheckDriver = DriverName;
  361. }
  362. FirstPrint = FALSE;
  363. }
  364. return;
  365. }
  366. //
  367. // Enable terminal output and turn on bugcheck processing.
  368. //
  369. VOID
  370. KiEnableHeadlessBlueScreen(
  371. )
  372. {
  373. HEADLESS_CMD_ENABLE_TERMINAL HeadlessCmd;
  374. HEADLESS_CMD_SEND_BLUE_SCREEN_DATA HeadlessCmdBlueScreen;
  375. HeadlessCmdBlueScreen.BugcheckCode = (ULONG)KiBugCheckData[0];
  376. HeadlessCmd.Enable = TRUE;
  377. HeadlessDispatch(HeadlessCmdStartBugCheck, NULL, 0, NULL, NULL);
  378. HeadlessDispatch(HeadlessCmdEnableTerminal,
  379. &HeadlessCmd,
  380. sizeof(HEADLESS_CMD_ENABLE_TERMINAL),
  381. NULL,
  382. NULL
  383. );
  384. HeadlessDispatch(HeadlessCmdSendBlueScreenData,
  385. &HeadlessCmdBlueScreen,
  386. sizeof(HEADLESS_CMD_SEND_BLUE_SCREEN_DATA),
  387. NULL,
  388. NULL
  389. );
  390. }
  391. VOID
  392. KiDisplayBlueScreen(
  393. IN ULONG PssMessage,
  394. IN BOOLEAN HardErrorCalled,
  395. IN PCHAR HardErrorCaption,
  396. IN PCHAR HardErrorMessage,
  397. IN PCHAR StateString
  398. )
  399. /*++
  400. Routine Description:
  401. Display the "Blue Screen of Death" with associated bluescreen information.
  402. The function is headless aware.
  403. Arguments:
  404. PssMessage - PSS message id.
  405. HardErrorCalled - Supplies a flag specifying whether the bluescreen
  406. was generated as a result of a harderror or not.
  407. HardErrorCaption - If HardErrorCalled is TRUE, supplies the harderror
  408. caption.
  409. HardErrorMessage - If HardErrorCalled is TRUE, supplies the harderror
  410. message.
  411. StateString - String containing the bugcheck driver name or state
  412. information about the crash.
  413. Return Value:
  414. None.
  415. --*/
  416. {
  417. CHAR Buffer [103];
  418. KiEnableHeadlessBlueScreen();
  419. //
  420. // Enable InbvDisplayString calls to make it through to bootvid driver.
  421. //
  422. if (InbvIsBootDriverInstalled()) {
  423. InbvAcquireDisplayOwnership();
  424. InbvResetDisplay();
  425. InbvSolidColorFill(0,0,639,479,4); // make the screen blue
  426. InbvSetTextColor(15);
  427. InbvInstallDisplayStringFilter((INBV_DISPLAY_STRING_FILTER)NULL);
  428. InbvEnableDisplayString(TRUE); // enable display string
  429. InbvSetScrollRegion(0,0,639,475); // set to use entire screen
  430. }
  431. if (!HardErrorCalled) {
  432. InbvDisplayString((PUCHAR)"\r\n");
  433. KeGetBugMessageText(BUGCHECK_MESSAGE_INTRO, NULL);
  434. InbvDisplayString((PUCHAR)"\r\n\r\n");
  435. if (KiBugCheckDriver) {
  436. //
  437. // Output the driver name.
  438. //
  439. KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL);
  440. KeBugCheckUnicodeToAnsi (KiBugCheckDriver,
  441. Buffer,
  442. sizeof (Buffer));
  443. InbvDisplayString((PUCHAR)" ");
  444. InbvDisplayString ((PUCHAR)Buffer);
  445. InbvDisplayString((PUCHAR)"\r\n\r\n");
  446. }
  447. //
  448. // Display the PSS message.
  449. // If we have no special text, get the text for the bugcode
  450. // which will be the bugcode name.
  451. //
  452. if (PssMessage == BUGCODE_PSS_MESSAGE) {
  453. KeGetBugMessageText((ULONG)KiBugCheckData[0], NULL);
  454. InbvDisplayString((PUCHAR)"\r\n\r\n");
  455. }
  456. KeGetBugMessageText(PSS_MESSAGE_INTRO, NULL);
  457. InbvDisplayString((PUCHAR)"\r\n\r\n");
  458. KeGetBugMessageText(PssMessage, NULL);
  459. InbvDisplayString((PUCHAR)"\r\n\r\n");
  460. KeGetBugMessageText(BUGCHECK_TECH_INFO, NULL);
  461. sprintf(Buffer,
  462. "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
  463. (ULONG)KiBugCheckData[0],
  464. (PVOID)KiBugCheckData[1],
  465. (PVOID)KiBugCheckData[2],
  466. (PVOID)KiBugCheckData[3],
  467. (PVOID)KiBugCheckData[4]);
  468. InbvDisplayString((PUCHAR)Buffer);
  469. if (KiBugCheckDriver) {
  470. InbvDisplayString((PUCHAR)StateString);
  471. }
  472. if (!KiBugCheckDriver) {
  473. KiDumpParameterImages(StateString,
  474. &(KiBugCheckData[1]),
  475. 4,
  476. KeBugCheckUnicodeToAnsi);
  477. }
  478. } else {
  479. if (HardErrorCaption) {
  480. InbvDisplayString((PUCHAR)HardErrorCaption);
  481. }
  482. if (HardErrorMessage) {
  483. InbvDisplayString((PUCHAR)HardErrorMessage);
  484. }
  485. }
  486. }
  487. #ifdef _X86_
  488. #pragma optimize("y", off) // RtlCaptureContext needs EBP to be correct
  489. #endif
  490. VOID
  491. KeBugCheck2 (
  492. IN ULONG BugCheckCode,
  493. IN ULONG_PTR BugCheckParameter1,
  494. IN ULONG_PTR BugCheckParameter2,
  495. IN ULONG_PTR BugCheckParameter3,
  496. IN ULONG_PTR BugCheckParameter4,
  497. IN PVOID SaveDataPage
  498. )
  499. /*++
  500. Routine Description:
  501. This function crashes the system in a controlled manner.
  502. Arguments:
  503. BugCheckCode - Supplies the reason for the bug check.
  504. BugCheckParameter1-4 - Supplies additional bug check information
  505. Return Value:
  506. None.
  507. --*/
  508. {
  509. // CHAR Buffer[103];
  510. CONTEXT ContextSave;
  511. ULONG PssMessage;
  512. PCHAR HardErrorCaption;
  513. PCHAR HardErrorMessage;
  514. KIRQL OldIrql;
  515. PKTRAP_FRAME TrapInformation;
  516. PVOID ExecutionAddress;
  517. PVOID ImageBase;
  518. PVOID VirtualAddress;
  519. PLDR_DATA_TABLE_ENTRY DataTableEntry;
  520. CHAR AnsiBuffer[100];
  521. PKTHREAD Thread;
  522. BOOLEAN InKernelOrHal;
  523. BOOLEAN Reboot;
  524. BOOLEAN HardErrorCalled;
  525. #if !defined(NT_UP)
  526. KAFFINITY TargetSet;
  527. #endif
  528. HardErrorCalled = FALSE;
  529. HardErrorCaption = NULL;
  530. HardErrorMessage = NULL;
  531. ExecutionAddress = NULL;
  532. Thread = KeGetCurrentThread();
  533. //
  534. // Initialization
  535. //
  536. Reboot = FALSE;
  537. KiBugCheckDriver = NULL;
  538. //
  539. // Try to simulate a power failure for Cluster testing
  540. //
  541. if (BugCheckCode == POWER_FAILURE_SIMULATE) {
  542. KiScanBugCheckCallbackList();
  543. HalReturnToFirmware(HalRebootRoutine);
  544. }
  545. //
  546. // Save the current IRQL in the Prcb so the debugger can extract it
  547. // later on for debugging purposes.
  548. //
  549. KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
  550. //
  551. // Capture the callers context as closely as possible into the debugger's
  552. // processor state area of the Prcb.
  553. //
  554. // N.B. There may be some prologue code that shuffles registers such that
  555. // they get destroyed.
  556. //
  557. #if defined(_X86_)
  558. KiSetHardwareTrigger();
  559. #else
  560. InterlockedIncrement64((LONGLONG volatile *)&KiHardwareTrigger);
  561. #endif
  562. RtlCaptureContext(&KeGetCurrentPrcb()->ProcessorState.ContextFrame);
  563. KiSaveProcessorControlState(&KeGetCurrentPrcb()->ProcessorState);
  564. //
  565. // This is necessary on machines where the virtual unwind that happens
  566. // during KeDumpMachineState() destroys the context record.
  567. //
  568. ContextSave = KeGetCurrentPrcb()->ProcessorState.ContextFrame;
  569. //
  570. // Stop the watchdog timer
  571. //
  572. if (ExpWdHandler != NULL) {
  573. ExpWdHandler( WdActionStopTimer, ExpWdHandlerContext, NULL, TRUE );
  574. }
  575. //
  576. // Get the correct string for bugchecks
  577. //
  578. switch (BugCheckCode) {
  579. case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
  580. case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
  581. case KMODE_EXCEPTION_NOT_HANDLED:
  582. PssMessage = KMODE_EXCEPTION_NOT_HANDLED;
  583. break;
  584. case DATA_BUS_ERROR:
  585. case NO_MORE_SYSTEM_PTES:
  586. case INACCESSIBLE_BOOT_DEVICE:
  587. case UNEXPECTED_KERNEL_MODE_TRAP:
  588. case ACPI_BIOS_ERROR:
  589. case ACPI_BIOS_FATAL_ERROR:
  590. case FAT_FILE_SYSTEM:
  591. case DRIVER_CORRUPTED_EXPOOL:
  592. case THREAD_STUCK_IN_DEVICE_DRIVER:
  593. PssMessage = BugCheckCode;
  594. break;
  595. case DRIVER_CORRUPTED_MMPOOL:
  596. PssMessage = DRIVER_CORRUPTED_EXPOOL;
  597. break;
  598. case NTFS_FILE_SYSTEM:
  599. PssMessage = FAT_FILE_SYSTEM;
  600. break;
  601. case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE:
  602. PssMessage = BUGCODE_PSS_MESSAGE_SIGNATURE;
  603. break;
  604. default:
  605. PssMessage = BUGCODE_PSS_MESSAGE;
  606. break;
  607. }
  608. //
  609. // Do further processing on bugcheck codes
  610. //
  611. KiBugCheckData[0] = BugCheckCode;
  612. KiBugCheckData[1] = BugCheckParameter1;
  613. KiBugCheckData[2] = BugCheckParameter2;
  614. KiBugCheckData[3] = BugCheckParameter3;
  615. KiBugCheckData[4] = BugCheckParameter4;
  616. switch (BugCheckCode) {
  617. case FATAL_UNHANDLED_HARD_ERROR:
  618. //
  619. // If we are called by hard error then we don't want to dump the
  620. // processor state on the machine.
  621. //
  622. // We know that we are called by hard error because the bug check
  623. // code will be FATAL_UNHANDLED_HARD_ERROR. If this is so then the
  624. // error status passed to harderr is the first parameter, and a pointer
  625. // to the parameter array from hard error is passed as the second
  626. // argument.
  627. //
  628. // The third argument is the OemCaption to be printed.
  629. // The last argument is the OemMessage to be printed.
  630. //
  631. {
  632. PULONG_PTR parameterArray;
  633. HardErrorCalled = TRUE;
  634. HardErrorCaption = (PCHAR)BugCheckParameter3;
  635. HardErrorMessage = (PCHAR)BugCheckParameter4;
  636. parameterArray = (PULONG_PTR)BugCheckParameter2;
  637. KiBugCheckData[0] = (ULONG)BugCheckParameter1;
  638. KiBugCheckData[1] = parameterArray[0];
  639. KiBugCheckData[2] = parameterArray[1];
  640. KiBugCheckData[3] = parameterArray[2];
  641. KiBugCheckData[4] = parameterArray[3];
  642. }
  643. break;
  644. case IRQL_NOT_LESS_OR_EQUAL:
  645. ExecutionAddress = (PVOID)BugCheckParameter4;
  646. if (ExecutionAddress >= ExPoolCodeStart && ExecutionAddress < ExPoolCodeEnd) {
  647. KiBugCheckData[0] = DRIVER_CORRUPTED_EXPOOL;
  648. }
  649. else if (ExecutionAddress >= MmPoolCodeStart && ExecutionAddress < MmPoolCodeEnd) {
  650. KiBugCheckData[0] = DRIVER_CORRUPTED_MMPOOL;
  651. }
  652. else if (ExecutionAddress >= MmPteCodeStart && ExecutionAddress < MmPteCodeEnd) {
  653. KiBugCheckData[0] = DRIVER_CORRUPTED_SYSPTES;
  654. }
  655. else {
  656. ImageBase = KiPcToFileHeader (ExecutionAddress,
  657. &DataTableEntry,
  658. FALSE,
  659. &InKernelOrHal);
  660. if (InKernelOrHal == TRUE) {
  661. //
  662. // The kernel faulted at raised IRQL. Quite often this
  663. // is a driver that has unloaded without deleting its
  664. // lookaside lists or other resources. Or its resources
  665. // are marked pagable and shouldn't be. Detect both
  666. // cases here and identify the offending driver
  667. // whenever possible.
  668. //
  669. VirtualAddress = (PVOID)BugCheckParameter1;
  670. ImageBase = KiPcToFileHeader (VirtualAddress,
  671. &DataTableEntry,
  672. TRUE,
  673. &InKernelOrHal);
  674. if (ImageBase != NULL) {
  675. KiBugCheckDriver = &DataTableEntry->BaseDllName;
  676. KiBugCheckData[0] = DRIVER_PORTION_MUST_BE_NONPAGED;
  677. }
  678. else {
  679. KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress);
  680. if (KiBugCheckDriver != NULL) {
  681. KiBugCheckData[0] = SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD;
  682. }
  683. }
  684. }
  685. else {
  686. KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
  687. }
  688. }
  689. ExecutionAddress = NULL;
  690. break;
  691. case ATTEMPTED_WRITE_TO_READONLY_MEMORY:
  692. case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY:
  693. TrapInformation = (PKTRAP_FRAME)BugCheckParameter3;
  694. //
  695. // Extract the execution address from the trap frame to
  696. // identify the component.
  697. //
  698. if (TrapInformation != NULL) {
  699. ExecutionAddress = (PVOID) PROGRAM_COUNTER (TrapInformation);
  700. }
  701. break;
  702. case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
  703. ExecutionAddress = (PVOID)BugCheckParameter1;
  704. break;
  705. case DRIVER_USED_EXCESSIVE_PTES:
  706. DataTableEntry = (PLDR_DATA_TABLE_ENTRY)BugCheckParameter1;
  707. KiBugCheckDriver = &DataTableEntry->BaseDllName;
  708. break;
  709. case PAGE_FAULT_IN_NONPAGED_AREA:
  710. ImageBase = NULL;
  711. //
  712. // Extract the execution address from the trap frame to
  713. // identify the component.
  714. //
  715. if (BugCheckParameter3) {
  716. ExecutionAddress = (PVOID)PROGRAM_COUNTER
  717. ((PKTRAP_FRAME)BugCheckParameter3);
  718. KiBugCheckData[3] = (ULONG_PTR)ExecutionAddress;
  719. ImageBase = KiPcToFileHeader (ExecutionAddress,
  720. &DataTableEntry,
  721. FALSE,
  722. &InKernelOrHal);
  723. }
  724. else {
  725. //
  726. // No trap frame, so no execution address either.
  727. //
  728. InKernelOrHal = TRUE;
  729. }
  730. VirtualAddress = (PVOID)BugCheckParameter1;
  731. if (MmIsSpecialPoolAddress (VirtualAddress) == TRUE) {
  732. //
  733. // Update the bugcheck number so the administrator gets
  734. // useful feedback that enabling special pool has enabled
  735. // the system to locate the corruptor.
  736. //
  737. if (MmIsSpecialPoolAddressFree (VirtualAddress) == TRUE) {
  738. if (InKernelOrHal == TRUE) {
  739. KiBugCheckData[0] = PAGE_FAULT_IN_FREED_SPECIAL_POOL;
  740. }
  741. else {
  742. KiBugCheckData[0] = DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL;
  743. }
  744. }
  745. else {
  746. if (InKernelOrHal == TRUE) {
  747. KiBugCheckData[0] = PAGE_FAULT_BEYOND_END_OF_ALLOCATION;
  748. }
  749. else {
  750. KiBugCheckData[0] = DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION;
  751. }
  752. }
  753. }
  754. else if ((ExecutionAddress == VirtualAddress) &&
  755. (MmIsSessionAddress (VirtualAddress) == TRUE) &&
  756. ((Thread->Teb == NULL) || (IS_SYSTEM_ADDRESS(Thread->Teb)))) {
  757. //
  758. // This is a driver reference to session space from a
  759. // worker thread. Since the system process has no session
  760. // space this is illegal and the driver must be fixed.
  761. //
  762. KiBugCheckData[0] = TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE;
  763. }
  764. else if (ImageBase == NULL) {
  765. KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress);
  766. if (KiBugCheckDriver != NULL) {
  767. KiBugCheckData[0] = DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS;
  768. }
  769. }
  770. break;
  771. case THREAD_STUCK_IN_DEVICE_DRIVER:
  772. KiBugCheckDriver = (PUNICODE_STRING) BugCheckParameter3;
  773. break;
  774. default:
  775. break;
  776. }
  777. if (KiBugCheckDriver) {
  778. KeBugCheckUnicodeToAnsi(KiBugCheckDriver,
  779. AnsiBuffer,
  780. sizeof(AnsiBuffer));
  781. } else {
  782. //
  783. // This will set KiBugCheckDriver to 1 if successful.
  784. //
  785. if (ExecutionAddress) {
  786. KiDumpParameterImages(AnsiBuffer,
  787. (PULONG_PTR)&ExecutionAddress,
  788. 1,
  789. KeBugCheckUnicodeToAnsi);
  790. }
  791. }
  792. if (KdPitchDebugger == FALSE ) {
  793. KdDebuggerDataBlock.SavedContext = (ULONG_PTR) &ContextSave;
  794. }
  795. //
  796. // If the user manually crashed the machine, skips the DbgPrints and
  797. // go to the crashdump.
  798. // Trying to do DbgPrint causes us to reeeter the debugger which causes
  799. // some problems.
  800. //
  801. // Otherwise, if the debugger is enabled, print out the information and
  802. // stop.
  803. //
  804. if ((BugCheckCode != MANUALLY_INITIATED_CRASH) &&
  805. (KdDebuggerEnabled)) {
  806. DbgPrint("\n*** Fatal System Error: 0x%08lx\n"
  807. " (0x%p,0x%p,0x%p,0x%p)\n\n",
  808. (ULONG)KiBugCheckData[0],
  809. KiBugCheckData[1],
  810. KiBugCheckData[2],
  811. KiBugCheckData[3],
  812. KiBugCheckData[4]);
  813. //
  814. // If the debugger is not actually connected, or the user manually
  815. // crashed the machine by typing .crash in the debugger, proceed to
  816. // "blue screen" the system.
  817. //
  818. // The call to DbgPrint above will have set the state of
  819. // KdDebuggerNotPresent if the debugger has become disconnected
  820. // since the system was booted.
  821. //
  822. if (KdDebuggerNotPresent == FALSE) {
  823. if (KiBugCheckDriver != NULL) {
  824. DbgPrint("Driver at fault: %s.\n", AnsiBuffer);
  825. }
  826. if (HardErrorCalled != FALSE) {
  827. if (HardErrorCaption) {
  828. DbgPrint(HardErrorCaption);
  829. }
  830. if (HardErrorMessage) {
  831. DbgPrint(HardErrorMessage);
  832. }
  833. }
  834. KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_FIRST);
  835. }
  836. }
  837. //
  838. // Freeze execution of the system by disabling interrupts and looping.
  839. //
  840. KeDisableInterrupts();
  841. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  842. //
  843. // Don't attempt to display message more than once.
  844. //
  845. if (InterlockedDecrement (&KeBugCheckCount) == 0) {
  846. #if !defined(NT_UP)
  847. //
  848. // Attempt to get the other processors frozen now, but don't wait
  849. // for them to freeze (in case someone is stuck).
  850. //
  851. TargetSet = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember;
  852. if (TargetSet != 0) {
  853. KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE);
  854. //
  855. // Give the other processors one second to flush their data caches.
  856. //
  857. // N.B. This cannot be synchronized since the reason for the bug
  858. // may be one of the other processors failed.
  859. //
  860. KeStallExecutionProcessor(1000 * 1000);
  861. }
  862. #endif
  863. //
  864. // Display the blue screen.
  865. //
  866. KiDisplayBlueScreen (PssMessage,
  867. HardErrorCalled,
  868. HardErrorCaption,
  869. HardErrorMessage,
  870. AnsiBuffer);
  871. //
  872. // Invoke bugcheck callbacks.
  873. //
  874. KiInvokeBugCheckEntryCallbacks();
  875. //
  876. // If the debugger is not enabled, attempt to enable it.
  877. //
  878. if (KdDebuggerEnabled == FALSE && KdPitchDebugger == FALSE ) {
  879. KdInitSystem(0, NULL);
  880. } else {
  881. InbvDisplayString((PUCHAR)"\r\n");
  882. }
  883. // Restore the original Context frame
  884. KeGetCurrentPrcb()->ProcessorState.ContextFrame = ContextSave;
  885. //
  886. // For some bugchecks we want to change the thread and context before
  887. // it is written to the dump file IFF it is a minidump.
  888. // Look at the original bugcheck data, not the processed data from
  889. // above
  890. //
  891. #define MINIDUMP_BUGCHECK 0x10000000
  892. if (IoIsTriageDumpEnabled()) {
  893. switch (BugCheckCode) {
  894. //
  895. // System thread stores a context record as the 4th parameter.
  896. // use that.
  897. // Also save the context record in case someone needs to look
  898. // at it.
  899. //
  900. case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
  901. if (BugCheckParameter4) {
  902. ContextSave = *((PCONTEXT)BugCheckParameter4);
  903. KiBugCheckData[0] |= MINIDUMP_BUGCHECK;
  904. }
  905. break;
  906. #if defined (_X86_)
  907. //
  908. // 3rd parameter is a trap frame.
  909. //
  910. // Build a context record out of that only if it's a kernel mode
  911. // failure because esp may be wrong in that case ???.
  912. //
  913. case ATTEMPTED_WRITE_TO_READONLY_MEMORY:
  914. case ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY:
  915. case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
  916. case PAGE_FAULT_IN_NONPAGED_AREA:
  917. if (BugCheckParameter3)
  918. {
  919. PKTRAP_FRAME Trap = (PKTRAP_FRAME) BugCheckParameter3;
  920. if ((Trap->SegCs & 1) ||
  921. (Trap->EFlags & EFLAGS_V86_MASK))
  922. {
  923. ContextSave.Esp = Trap->HardwareEsp;
  924. }
  925. else
  926. {
  927. ContextSave.Esp = (ULONG)Trap +
  928. FIELD_OFFSET(KTRAP_FRAME, HardwareEsp);
  929. }
  930. if (Trap->EFlags & EFLAGS_V86_MASK)
  931. {
  932. ContextSave.SegSs = Trap->HardwareSegSs & 0xffff;
  933. }
  934. else if (Trap->SegCs & 1)
  935. {
  936. //
  937. // It's user mode.
  938. // The HardwareSegSs contains R3 data selector.
  939. //
  940. ContextSave.SegSs =
  941. (Trap->HardwareSegSs | 3) & 0xffff;
  942. }
  943. else
  944. {
  945. ContextSave.SegSs = KGDT_R0_DATA;
  946. }
  947. ContextSave.SegGs = Trap->SegGs & 0xffff;
  948. ContextSave.SegFs = Trap->SegFs & 0xffff;
  949. ContextSave.SegEs = Trap->SegEs & 0xffff;
  950. ContextSave.SegDs = Trap->SegDs & 0xffff;
  951. ContextSave.SegCs = Trap->SegCs & 0xffff;
  952. ContextSave.Eip = Trap->Eip;
  953. ContextSave.Ebp = Trap->Ebp;
  954. ContextSave.Eax = Trap->Eax;
  955. ContextSave.Ebx = Trap->Ebx;
  956. ContextSave.Ecx = Trap->Ecx;
  957. ContextSave.Edx = Trap->Edx;
  958. ContextSave.Edi = Trap->Edi;
  959. ContextSave.Esi = Trap->Esi;
  960. ContextSave.EFlags = Trap->EFlags;
  961. KiBugCheckData[0] |= MINIDUMP_BUGCHECK;
  962. }
  963. break;
  964. case THREAD_STUCK_IN_DEVICE_DRIVER:
  965. // Extract the address of the spinning code from the thread
  966. // object, so the dump is based off this thread.
  967. Thread = (PKTHREAD) BugCheckParameter1;
  968. if (Thread->State == Running)
  969. {
  970. //
  971. // If the thread was running, the thread is now in a
  972. // frozen state and the registers are in the PRCB
  973. // context
  974. //
  975. ULONG Processor = Thread->NextProcessor;
  976. ASSERT(Processor < (ULONG) KeNumberProcessors);
  977. ContextSave =
  978. KiProcessorBlock[Processor]->ProcessorState.ContextFrame;
  979. }
  980. else
  981. {
  982. //
  983. // This should be a uniproc machine, and the thread
  984. // should be suspended. Just get the data off the
  985. // switch frame.
  986. //
  987. PKSWITCHFRAME SwitchFrame = (PKSWITCHFRAME)Thread->KernelStack;
  988. ASSERT(Thread->State == Ready);
  989. ContextSave.Esp = (ULONG)Thread->KernelStack + sizeof(KSWITCHFRAME);
  990. ContextSave.Ebp = *((PULONG)(ContextSave.Esp));
  991. ContextSave.Eip = SwitchFrame->RetAddr;
  992. }
  993. KiBugCheckData[0] |= MINIDUMP_BUGCHECK;
  994. break;
  995. case UNEXPECTED_KERNEL_MODE_TRAP:
  996. //
  997. // Double fault
  998. //
  999. if (BugCheckParameter1 == 0x8)
  1000. {
  1001. // The thread is correct in this case.
  1002. // Second parameter is the TSS. If we have a TSS, convert
  1003. // the context and mark the bugcheck as converted.
  1004. PKTSS Tss = (PKTSS) BugCheckParameter2;
  1005. if (Tss)
  1006. {
  1007. if (Tss->EFlags & EFLAGS_V86_MASK)
  1008. {
  1009. ContextSave.SegSs = Tss->Ss & 0xffff;
  1010. }
  1011. else if (Tss->Cs & 1)
  1012. {
  1013. //
  1014. // It's user mode.
  1015. // The HardwareSegSs contains R3 data selector.
  1016. //
  1017. ContextSave.SegSs = (Tss->Ss | 3) & 0xffff;
  1018. }
  1019. else
  1020. {
  1021. ContextSave.SegSs = KGDT_R0_DATA;
  1022. }
  1023. ContextSave.SegGs = Tss->Gs & 0xffff;
  1024. ContextSave.SegFs = Tss->Fs & 0xffff;
  1025. ContextSave.SegEs = Tss->Es & 0xffff;
  1026. ContextSave.SegDs = Tss->Ds & 0xffff;
  1027. ContextSave.SegCs = Tss->Cs & 0xffff;
  1028. ContextSave.Esp = Tss->Esp;
  1029. ContextSave.Eip = Tss->Eip;
  1030. ContextSave.Ebp = Tss->Ebp;
  1031. ContextSave.Eax = Tss->Eax;
  1032. ContextSave.Ebx = Tss->Ebx;
  1033. ContextSave.Ecx = Tss->Ecx;
  1034. ContextSave.Edx = Tss->Edx;
  1035. ContextSave.Edi = Tss->Edi;
  1036. ContextSave.Esi = Tss->Esi;
  1037. ContextSave.EFlags = Tss->EFlags;
  1038. }
  1039. KiBugCheckData[0] |= MINIDUMP_BUGCHECK;
  1040. break;
  1041. }
  1042. #endif
  1043. default:
  1044. break;
  1045. }
  1046. //
  1047. // Write a crash dump and optionally reboot if the system has been
  1048. // so configured.
  1049. //
  1050. IoAddTriageDumpDataBlock(PAGE_ALIGN(KiBugCheckData[1]), PAGE_SIZE);
  1051. IoAddTriageDumpDataBlock(PAGE_ALIGN(KiBugCheckData[2]), PAGE_SIZE);
  1052. IoAddTriageDumpDataBlock(PAGE_ALIGN(KiBugCheckData[3]), PAGE_SIZE);
  1053. IoAddTriageDumpDataBlock(PAGE_ALIGN(KiBugCheckData[4]), PAGE_SIZE);
  1054. IoAddTriageDumpDataBlock(PAGE_ALIGN(SaveDataPage), PAGE_SIZE);
  1055. //
  1056. // If the DPC stack is active, save that data page as well.
  1057. //
  1058. #if defined (_X86_)
  1059. if (KeGetCurrentPrcb()->DpcRoutineActive)
  1060. {
  1061. IoAddTriageDumpDataBlock(PAGE_ALIGN(KeGetCurrentPrcb()->DpcRoutineActive), PAGE_SIZE);
  1062. }
  1063. #endif
  1064. }
  1065. IoWriteCrashDump((ULONG)KiBugCheckData[0],
  1066. KiBugCheckData[1],
  1067. KiBugCheckData[2],
  1068. KiBugCheckData[3],
  1069. KiBugCheckData[4],
  1070. &ContextSave,
  1071. Thread,
  1072. &Reboot);
  1073. }
  1074. //
  1075. // Invoke bugcheck callbacks after crashdump, so the callbacks will
  1076. // not prevent us from crashdumping.
  1077. //
  1078. KiScanBugCheckCallbackList();
  1079. //
  1080. // Start the watchdog timer
  1081. //
  1082. if (ExpWdHandler != NULL) {
  1083. ExpWdHandler( WdActionStartTimer, ExpWdHandlerContext, NULL, TRUE );
  1084. }
  1085. //
  1086. // Reboot the machine if necessary.
  1087. //
  1088. if (Reboot) {
  1089. DbgUnLoadImageSymbols (NULL, (PVOID)-1, 0);
  1090. HalReturnToFirmware (HalRebootRoutine);
  1091. }
  1092. //
  1093. // Attempt to enter the kernel debugger.
  1094. //
  1095. KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_SECOND);
  1096. }
  1097. #ifdef _X86_
  1098. #pragma optimize("", on)
  1099. #endif
  1100. VOID
  1101. KeEnterKernelDebugger (
  1102. VOID
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. This function crashes the system in a controlled manner attempting
  1107. to invoke the kernel debugger.
  1108. Arguments:
  1109. None.
  1110. Return Value:
  1111. None.
  1112. --*/
  1113. {
  1114. #if !defined(i386)
  1115. KIRQL OldIrql;
  1116. #endif
  1117. //
  1118. // Freeze execution of the system by disabling interrupts and looping.
  1119. //
  1120. KiHardwareTrigger = 1;
  1121. KeDisableInterrupts();
  1122. #if !defined(i386)
  1123. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  1124. #endif
  1125. if (InterlockedDecrement (&KeBugCheckCount) == 0) {
  1126. if (KdDebuggerEnabled == FALSE) {
  1127. if ( KdPitchDebugger == FALSE ) {
  1128. KdInitSystem(0, NULL);
  1129. }
  1130. }
  1131. }
  1132. KiBugCheckDebugBreak (DBG_STATUS_FATAL);
  1133. }
  1134. NTKERNELAPI
  1135. BOOLEAN
  1136. KeDeregisterBugCheckCallback (
  1137. IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This function deregisters a bug check callback record.
  1142. Arguments:
  1143. CallbackRecord - Supplies a pointer to a bug check callback record.
  1144. Return Value:
  1145. If the specified bug check callback record is successfully deregistered,
  1146. then a value of TRUE is returned. Otherwise, a value of FALSE is returned.
  1147. --*/
  1148. {
  1149. BOOLEAN Deregister;
  1150. KIRQL OldIrql;
  1151. //
  1152. // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
  1153. // spinlock.
  1154. //
  1155. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  1156. KiAcquireSpinLock(&KeBugCheckCallbackLock);
  1157. //
  1158. // If the specified callback record is currently registered, then
  1159. // deregister the callback record.
  1160. //
  1161. Deregister = FALSE;
  1162. if (CallbackRecord->State == BufferInserted) {
  1163. CallbackRecord->State = BufferEmpty;
  1164. RemoveEntryList(&CallbackRecord->Entry);
  1165. Deregister = TRUE;
  1166. }
  1167. //
  1168. // Release the bug check callback spinlock, lower IRQL to its previous
  1169. // value, and return whether the callback record was successfully
  1170. // deregistered.
  1171. //
  1172. KiReleaseSpinLock(&KeBugCheckCallbackLock);
  1173. KeLowerIrql(OldIrql);
  1174. return Deregister;
  1175. }
  1176. NTKERNELAPI
  1177. BOOLEAN
  1178. KeRegisterBugCheckCallback (
  1179. IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
  1180. IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
  1181. IN PVOID Buffer,
  1182. IN ULONG Length,
  1183. IN PUCHAR Component
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This function registers a bug check callback record. If the system
  1188. crashes, then the specified function will be called during bug check
  1189. processing so it may dump additional state in the specified bug check
  1190. buffer.
  1191. N.B. Bug check callback routines are called in reverse order of
  1192. registration, i.e., in LIFO order.
  1193. Arguments:
  1194. CallbackRecord - Supplies a pointer to a callback record.
  1195. CallbackRoutine - Supplies a pointer to the callback routine.
  1196. Buffer - Supplies a pointer to the bug check buffer.
  1197. Length - Supplies the length of the bug check buffer in bytes.
  1198. Component - Supplies a pointer to a zero terminated component
  1199. identifier.
  1200. Return Value:
  1201. If the specified bug check callback record is successfully registered,
  1202. then a value of TRUE is returned. Otherwise, a value of FALSE is returned.
  1203. --*/
  1204. {
  1205. BOOLEAN Inserted;
  1206. KIRQL OldIrql;
  1207. //
  1208. // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
  1209. // spinlock.
  1210. //
  1211. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  1212. KiAcquireSpinLock(&KeBugCheckCallbackLock);
  1213. //
  1214. // If the specified callback record is currently not registered, then
  1215. // register the callback record.
  1216. //
  1217. Inserted = FALSE;
  1218. if (CallbackRecord->State == BufferEmpty) {
  1219. CallbackRecord->CallbackRoutine = CallbackRoutine;
  1220. CallbackRecord->Buffer = Buffer;
  1221. CallbackRecord->Length = Length;
  1222. CallbackRecord->Component = Component;
  1223. CallbackRecord->Checksum =
  1224. ((ULONG_PTR)CallbackRoutine + (ULONG_PTR)Buffer + Length + (ULONG_PTR)Component);
  1225. CallbackRecord->State = BufferInserted;
  1226. InsertHeadList(&KeBugCheckCallbackListHead, &CallbackRecord->Entry);
  1227. Inserted = TRUE;
  1228. }
  1229. //
  1230. // Release the bug check callback spinlock, lower IRQL to its previous
  1231. // value, and return whether the callback record was successfully
  1232. // registered.
  1233. //
  1234. KiReleaseSpinLock(&KeBugCheckCallbackLock);
  1235. KeLowerIrql(OldIrql);
  1236. return Inserted;
  1237. }
  1238. VOID
  1239. KiScanBugCheckCallbackList (
  1240. VOID
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. This function scans the bug check callback list and calls each bug
  1245. check callback routine so it can dump component specific information
  1246. that may identify the cause of the bug check.
  1247. N.B. The scan of the bug check callback list is performed VERY
  1248. carefully. Bug check callback routines are called at HIGH_LEVEL
  1249. and may not acquire ANY resources.
  1250. Arguments:
  1251. None.
  1252. Return Value:
  1253. None.
  1254. --*/
  1255. {
  1256. PKBUGCHECK_CALLBACK_RECORD CallbackRecord;
  1257. ULONG_PTR Checksum;
  1258. ULONG Index;
  1259. PLIST_ENTRY LastEntry;
  1260. PLIST_ENTRY ListHead;
  1261. PLIST_ENTRY NextEntry;
  1262. PUCHAR Source;
  1263. //
  1264. // If the bug check callback listhead is not initialized, then the
  1265. // bug check has occured before the system has gotten far enough
  1266. // in the initialization code to enable anyone to register a callback.
  1267. //
  1268. ListHead = &KeBugCheckCallbackListHead;
  1269. if ((ListHead->Flink != NULL) && (ListHead->Blink != NULL)) {
  1270. //
  1271. // Scan the bug check callback list.
  1272. //
  1273. LastEntry = ListHead;
  1274. NextEntry = ListHead->Flink;
  1275. while (NextEntry != ListHead) {
  1276. //
  1277. // The next entry address must be aligned properly, the
  1278. // callback record must be readable, and the callback record
  1279. // must have back link to the last entry.
  1280. //
  1281. if (((ULONG_PTR)NextEntry & (sizeof(ULONG_PTR) - 1)) != 0) {
  1282. return;
  1283. } else {
  1284. CallbackRecord = CONTAINING_RECORD(NextEntry,
  1285. KBUGCHECK_CALLBACK_RECORD,
  1286. Entry);
  1287. Source = (PUCHAR)CallbackRecord;
  1288. for (Index = 0; Index < sizeof(KBUGCHECK_CALLBACK_RECORD); Index += 1) {
  1289. if (MmIsAddressValid((PVOID)Source) == FALSE) {
  1290. return;
  1291. }
  1292. Source += 1;
  1293. }
  1294. if (CallbackRecord->Entry.Blink != LastEntry) {
  1295. return;
  1296. }
  1297. //
  1298. // If the callback record has a state of inserted and the
  1299. // computed checksum matches the callback record checksum,
  1300. // then call the specified bug check callback routine.
  1301. //
  1302. Checksum = (ULONG_PTR)CallbackRecord->CallbackRoutine;
  1303. Checksum += (ULONG_PTR)CallbackRecord->Buffer;
  1304. Checksum += CallbackRecord->Length;
  1305. Checksum += (ULONG_PTR)CallbackRecord->Component;
  1306. if ((CallbackRecord->State == BufferInserted) &&
  1307. (CallbackRecord->Checksum == Checksum)) {
  1308. //
  1309. // Call the specified bug check callback routine and
  1310. // handle any exceptions that occur.
  1311. //
  1312. CallbackRecord->State = BufferStarted;
  1313. try {
  1314. (CallbackRecord->CallbackRoutine)(CallbackRecord->Buffer,
  1315. CallbackRecord->Length);
  1316. CallbackRecord->State = BufferFinished;
  1317. } except(EXCEPTION_EXECUTE_HANDLER) {
  1318. CallbackRecord->State = BufferIncomplete;
  1319. }
  1320. }
  1321. }
  1322. LastEntry = NextEntry;
  1323. NextEntry = NextEntry->Flink;
  1324. }
  1325. }
  1326. return;
  1327. }
  1328. NTKERNELAPI
  1329. BOOLEAN
  1330. KeDeregisterBugCheckReasonCallback (
  1331. IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. This function deregisters a bug check callback record.
  1336. Arguments:
  1337. CallbackRecord - Supplies a pointer to a bug check callback record.
  1338. Return Value:
  1339. If the specified bug check callback record is successfully deregistered,
  1340. then a value of TRUE is returned. Otherwise, a value of FALSE is returned.
  1341. --*/
  1342. {
  1343. BOOLEAN Deregister;
  1344. KIRQL OldIrql;
  1345. //
  1346. // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
  1347. // spinlock.
  1348. //
  1349. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  1350. KiAcquireSpinLock(&KeBugCheckCallbackLock);
  1351. //
  1352. // If the specified callback record is currently registered, then
  1353. // deregister the callback record.
  1354. //
  1355. Deregister = FALSE;
  1356. if (CallbackRecord->State == BufferInserted) {
  1357. CallbackRecord->State = BufferEmpty;
  1358. RemoveEntryList(&CallbackRecord->Entry);
  1359. Deregister = TRUE;
  1360. }
  1361. //
  1362. // Release the bug check callback spinlock, lower IRQL to its previous
  1363. // value, and return whether the callback record was successfully
  1364. // deregistered.
  1365. //
  1366. KiReleaseSpinLock(&KeBugCheckCallbackLock);
  1367. KeLowerIrql(OldIrql);
  1368. return Deregister;
  1369. }
  1370. NTKERNELAPI
  1371. BOOLEAN
  1372. KeRegisterBugCheckReasonCallback (
  1373. IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
  1374. IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
  1375. IN KBUGCHECK_CALLBACK_REASON Reason,
  1376. IN PUCHAR Component
  1377. )
  1378. /*++
  1379. Routine Description:
  1380. This function registers a bug check callback record. If the system
  1381. crashes, then the specified function will be called during bug check
  1382. processing.
  1383. N.B. Bug check callback routines are called in reverse order of
  1384. registration, i.e., in LIFO order.
  1385. Arguments:
  1386. CallbackRecord - Supplies a pointer to a callback record.
  1387. CallbackRoutine - Supplies a pointer to the callback routine.
  1388. Reason - Specifies the conditions under which the callback
  1389. should be called.
  1390. Component - Supplies a pointer to a zero terminated component
  1391. identifier.
  1392. Return Value:
  1393. If the specified bug check callback record is successfully registered,
  1394. then a value of TRUE is returned. Otherwise, a value of FALSE is returned.
  1395. --*/
  1396. {
  1397. BOOLEAN Inserted;
  1398. KIRQL OldIrql;
  1399. //
  1400. // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
  1401. // spinlock.
  1402. //
  1403. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  1404. KiAcquireSpinLock(&KeBugCheckCallbackLock);
  1405. //
  1406. // If the specified callback record is currently not registered, then
  1407. // register the callback record.
  1408. //
  1409. Inserted = FALSE;
  1410. if (CallbackRecord->State == BufferEmpty) {
  1411. CallbackRecord->CallbackRoutine = CallbackRoutine;
  1412. CallbackRecord->Reason = Reason;
  1413. CallbackRecord->Component = Component;
  1414. CallbackRecord->Checksum =
  1415. ((ULONG_PTR)CallbackRoutine + Reason + (ULONG_PTR)Component);
  1416. CallbackRecord->State = BufferInserted;
  1417. InsertHeadList(&KeBugCheckReasonCallbackListHead,
  1418. &CallbackRecord->Entry);
  1419. Inserted = TRUE;
  1420. }
  1421. //
  1422. // Release the bug check callback spinlock, lower IRQL to its previous
  1423. // value, and return whether the callback record was successfully
  1424. // registered.
  1425. //
  1426. KiReleaseSpinLock(&KeBugCheckCallbackLock);
  1427. KeLowerIrql(OldIrql);
  1428. return Inserted;
  1429. }
  1430. VOID
  1431. KiInvokeBugCheckEntryCallbacks (
  1432. VOID
  1433. )
  1434. /*++
  1435. Routine Description:
  1436. This function scans the bug check reason callback list and calls
  1437. each bug check entry callback routine.
  1438. This may seem like a duplication of KiScanBugCheckCallbackList
  1439. but the critical difference is that the bug check entry callbacks
  1440. are called immediately upon entry to KeBugCheck2 whereas
  1441. KSBCCL does not invoke its callbacks until after all bug check
  1442. processing has finished.
  1443. In order to avoid people from abusing this callback it's
  1444. semi-private and the reason -- KbCallbackReserved1 -- has
  1445. an obscure name.
  1446. N.B. The scan of the bug check callback list is performed VERY
  1447. carefully. Bug check callback routines may be called at HIGH_LEVEL
  1448. and may not acquire ANY resources.
  1449. Arguments:
  1450. None.
  1451. Return Value:
  1452. None.
  1453. --*/
  1454. {
  1455. PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord;
  1456. ULONG_PTR Checksum;
  1457. PLIST_ENTRY LastEntry;
  1458. PLIST_ENTRY ListHead;
  1459. PLIST_ENTRY NextEntry;
  1460. PUCHAR Va;
  1461. ULONG Pages;
  1462. //
  1463. // If the bug check callback listhead is not initialized, then the
  1464. // bug check has occured before the system has gotten far enough
  1465. // in the initialization code to enable anyone to register a callback.
  1466. //
  1467. ListHead = &KeBugCheckReasonCallbackListHead;
  1468. if (ListHead->Flink == NULL || ListHead->Blink == NULL) {
  1469. return;
  1470. }
  1471. //
  1472. // Scan the bug check callback list.
  1473. //
  1474. LastEntry = ListHead;
  1475. NextEntry = ListHead->Flink;
  1476. while (NextEntry != ListHead) {
  1477. //
  1478. // The next entry address must be aligned properly, the
  1479. // callback record must be readable, and the callback record
  1480. // must have back link to the last entry.
  1481. //
  1482. if (((ULONG_PTR)NextEntry & (sizeof(ULONG_PTR) - 1)) != 0) {
  1483. return;
  1484. }
  1485. CallbackRecord = CONTAINING_RECORD(NextEntry,
  1486. KBUGCHECK_REASON_CALLBACK_RECORD,
  1487. Entry);
  1488. //
  1489. // Verify that the callback record is still valid.
  1490. //
  1491. Va = (PUCHAR) PAGE_ALIGN (CallbackRecord);
  1492. Pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (CallbackRecord,
  1493. sizeof (*CallbackRecord));
  1494. while (Pages) {
  1495. if (!MmIsAddressValid (Va)) {
  1496. return;
  1497. }
  1498. Va += PAGE_SIZE;
  1499. Pages--;
  1500. }
  1501. if (CallbackRecord->Entry.Blink != LastEntry) {
  1502. return;
  1503. }
  1504. LastEntry = NextEntry;
  1505. NextEntry = NextEntry->Flink;
  1506. //
  1507. // If the callback record has a state of inserted and the
  1508. // computed checksum matches the callback record checksum,
  1509. // then call the specified bug check callback routine.
  1510. //
  1511. Checksum = (ULONG_PTR)CallbackRecord->CallbackRoutine;
  1512. Checksum += (ULONG_PTR)CallbackRecord->Reason;
  1513. Checksum += (ULONG_PTR)CallbackRecord->Component;
  1514. if ((CallbackRecord->State != BufferInserted) ||
  1515. (CallbackRecord->Checksum != Checksum) ||
  1516. (CallbackRecord->Reason != KbCallbackReserved1) ||
  1517. MmIsAddressValid((PVOID)(ULONG_PTR)CallbackRecord->
  1518. CallbackRoutine) == FALSE) {
  1519. continue;
  1520. }
  1521. //
  1522. // Call the specified bug check callback routine and
  1523. // handle any exceptions that occur.
  1524. //
  1525. try {
  1526. (CallbackRecord->CallbackRoutine)(KbCallbackReserved1,
  1527. CallbackRecord,
  1528. NULL, 0);
  1529. CallbackRecord->State = BufferFinished;
  1530. } except(EXCEPTION_EXECUTE_HANDLER) {
  1531. CallbackRecord->State = BufferIncomplete;
  1532. }
  1533. }
  1534. }