Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbug.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
1.7.6.1
|