VOID KiBugCheckDebugBreak ( IN ULONG BreakStatus ) { do { try { // // Issue a breakpoint // DbgBreakPointWithStatus (BreakStatus); } except(EXCEPTION_EXECUTE_HANDLER) { // // Failure to issue breakpoint, halt the system // try { HalHaltSystem(); } except(EXCEPTION_EXECUTE_HANDLER) { for (;;) { } } for (;;) { } } } while (BreakStatus != DBG_STATUS_BUGCHECK_FIRST); }
/*++ Routine Description: Clock interrupt handler for processor 0. Arguments: Interrupt ServiceContext TrapFrame Return Value: TRUE --*/ BOOLEAN HalpHandleDecrementerInterrupt( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext, IN PVOID TrapFrame ) { KIRQL OldIrql; static int recurse = FALSE; ULONG CpuId; HASSERT(!MSR(EE)); CpuId = GetCpuId(); // // Raise irql via updating the PCR // OldIrql = PCR->CurrentIrql; PCR->CurrentIrql = CLOCK2_LEVEL; RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); // // Reset DECREMENTER, accounting for interrupt latency. // HalpUpdateDecrementer(HalpClockCount); // // Call the kernel to update system time // KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement); HalpCurrentTimeIncrement = HalpNewTimeIncrement; if (!recurse) { // // In some circumstances the KdPollBreakIn can // take longer than a decrementer interrupt // to complete. This is do to a conflict // between DMA and PIO. For now, just avoid // recursing into the debugger check. // recurse = TRUE; if (KdDebuggerEnabled && KdPollBreakIn()) { HalpEnableInterrupts(); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); HalpDisableInterrupts(); } recurse = FALSE; } // // Lower Irql to original value and enable interrupts // PCR->CurrentIrql = OldIrql; RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); return (TRUE); }
/*++ Routine Description: Clock interrupt handler for processors other than 0. Arguments: Interrupt ServiceContext TrapFrame Return Value: TRUE --*/ BOOLEAN HalpHandleDecrementerInterrupt1( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext, IN PVOID TrapFrame ) { KIRQL OldIrql; ULONG CpuId; HASSERT(!MSR(EE)); CpuId = GetCpuId(); // // Raise irql via updating the PCR // OldIrql = PCR->CurrentIrql; PCR->CurrentIrql = CLOCK2_LEVEL; RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); // // Reset DECREMENTER (no account for latency) // HalpUpdateDecrementer(HalpFullTickClockCount); // // Call the kernel to update run time for this thread and process. // KeUpdateRunTime(TrapFrame); HDBG(DBG_PROC1DBG, { // // Check for the debugger BreakIn only every minute or so. // (decrementer is interms of ms so we multiple by 10,000 // on the order of a minute). // static Count = 0; if (++Count > 10000) { Count = 0; if (KdDebuggerEnabled && KdPollBreakIn()) { HalpEnableInterrupts(); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); HalpDisableInterrupts(); } } } );
VOID NTAPI KiBugCheckDebugBreak(IN ULONG StatusCode) { /* * Wrap this in SEH so we don't crash if * there is no debugger or if it disconnected */ DoBreak: _SEH2_TRY { /* Breakpoint */ DbgBreakPointWithStatus(StatusCode); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* No debugger, halt the CPU */ HalHaltSystem(); } _SEH2_END; /* Break again if this wasn't first try */ if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak; }
VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KIRQL Irql) { PKPRCB Prcb = KeGetCurrentPrcb(); ULARGE_INTEGER CurrentTime, InterruptTime; LONG OldTickOffset; /* Check if this tick is being skipped */ if (Prcb->SkipTick) { /* Handle it next time */ Prcb->SkipTick = FALSE; /* Increase interrupt count and end the interrupt */ Prcb->InterruptCount++; KiEndInterrupt(Irql, TrapFrame); /* Note: non-x86 return back to the caller! */ return; } /* Add the increment time to the shared data */ InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime; InterruptTime.QuadPart += Increment; KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime); /* Check for timer expiration */ KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); /* Update the tick offset */ OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment); /* If the debugger is enabled, check for break-in request */ if (KdDebuggerEnabled && KdPollBreakIn()) { /* Break-in requested! */ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } /* Check for full tick */ if (OldTickOffset <= (LONG)Increment) { /* Update the system time */ CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime; CurrentTime.QuadPart += KeTimeAdjustment; KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime); /* Update the tick count */ CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1; KiWriteSystemTime(&KeTickCount, CurrentTime); /* Update it in the shared user data */ KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime); /* Check for expiration with the new tick count as well */ KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); /* Reset the tick offset */ KiTickOffset += KeMaximumIncrement; /* Update processor/thread runtime */ KeUpdateRunTime(TrapFrame, Irql); } else { /* Increase interrupt count only */ Prcb->InterruptCount++; } /* Disable interrupts and end the interrupt */ KiEndInterrupt(Irql, TrapFrame); }
BOOLEAN NTAPI i8042KbdInterruptService( IN PKINTERRUPT Interrupt, PVOID Context) { PI8042_KEYBOARD_EXTENSION DeviceExtension; PPORT_DEVICE_EXTENSION PortDeviceExtension; PKEYBOARD_INPUT_DATA InputData; ULONG Counter; UCHAR PortStatus = 0, Output = 0; BOOLEAN ToReturn = FALSE; NTSTATUS Status; UNREFERENCED_PARAMETER(Interrupt); __analysis_assume(Context != NULL); DeviceExtension = Context; PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer; Counter = PortDeviceExtension->Settings.PollStatusIterations; while (Counter) { Status = i8042ReadStatus(PortDeviceExtension, &PortStatus); if (!NT_SUCCESS(Status)) { WARN_(I8042PRT, "i8042ReadStatus() failed with status 0x%08lx\n", Status); return FALSE; } Status = i8042ReadKeyboardData(PortDeviceExtension, &Output); if (NT_SUCCESS(Status)) break; KeStallExecutionProcessor(1); Counter--; } if (Counter == 0) { WARN_(I8042PRT, "Spurious i8042 keyboard interrupt\n"); return FALSE; } INFO_(I8042PRT, "Got: 0x%02x\n", Output); if (PortDeviceExtension->Settings.CrashOnCtrlScroll) { /* Test for CTRL + SCROLL LOCK twice */ static const UCHAR ScanCodes[] = { 0x1d, 0x46, 0xc6, 0x46, 0 }; if (Output == ScanCodes[DeviceExtension->ComboPosition]) { DeviceExtension->ComboPosition++; if (ScanCodes[DeviceExtension->ComboPosition] == 0) KeBugCheck(MANUALLY_INITIATED_CRASH); } else if (Output == 0xfa) { /* Ignore ACK */ } else if (Output == ScanCodes[0]) DeviceExtension->ComboPosition = 1; else DeviceExtension->ComboPosition = 0; /* Test for TAB + key combination */ if (InputData->MakeCode == 0x0F) DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK); else if (DeviceExtension->TabPressed) { DeviceExtension->TabPressed = FALSE; /* Check which action to do */ if (InputData->MakeCode == 0x25) { /* k - Breakpoint */ DbgBreakPointWithStatus(DBG_STATUS_SYSRQ); } else if (InputData->MakeCode == 0x30) { /* b - Bugcheck */ KeBugCheck(MANUALLY_INITIATED_CRASH); } #if defined(KDBG) else { /* Send request to the kernel debugger. * Unknown requests will be ignored. */ KdSystemDebugControl(' soR', (PVOID)(ULONG_PTR)InputData->MakeCode, 0, NULL, 0, NULL, KernelMode); } #endif } } if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn)) return ToReturn; if (i8042PacketIsr(PortDeviceExtension, Output)) { if (PortDeviceExtension->PacketComplete) { TRACE_(I8042PRT, "Packet complete\n"); KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL); } TRACE_(I8042PRT, "Irq eaten by packet\n"); return TRUE; } TRACE_(I8042PRT, "Irq is keyboard input\n"); if (DeviceExtension->KeyboardScanState == Normal) { switch (Output) { case 0xe0: DeviceExtension->KeyboardScanState = GotE0; return TRUE; case 0xe1: DeviceExtension->KeyboardScanState = GotE1; return TRUE; default: break; } } /* Update InputData */ InputData->Flags = 0; switch (DeviceExtension->KeyboardScanState) { case GotE0: InputData->Flags |= KEY_E0; break; case GotE1: InputData->Flags |= KEY_E1; break; default: break; } DeviceExtension->KeyboardScanState = Normal; if (Output & 0x80) InputData->Flags |= KEY_BREAK; else InputData->Flags |= KEY_MAKE; InputData->MakeCode = Output & 0x7f; InputData->Reserved = 0; DeviceExtension->KeyboardHook.QueueKeyboardPacket(DeviceExtension->KeyboardHook.CallContext); return TRUE; }
VOID ExpDebuggerWorker( IN PVOID Context ) /*++ Routine Description: This is a worker thread for the kernel debugger that can be used to perform certain tasks on the target machine asynchronously. This is necessary when the machine needs to run at Dispatch level to perform certain operations, such as paging in data. Arguments: Context - not used as this point. Return Value: None. --*/ { NTSTATUS Status; KAPC_STATE ApcState; volatile UCHAR Data; PRKPROCESS KillProcess = (PRKPROCESS) ExpDebuggerProcessKill; PRKPROCESS AttachProcess = (PRKPROCESS) ExpDebuggerProcessAttach; PUCHAR PageIn = (PUCHAR) ExpDebuggerPageIn; PEPROCESS Process; ExpDebuggerProcessKill = 0; ExpDebuggerProcessAttach = 0; ExpDebuggerPageIn = 0; UNREFERENCED_PARAMETER (Context); #if DBG if (ExpDebuggerWork != 2) { DbgPrint("ExpDebuggerWorker being entered with state != 2\n"); } #endif ExpDebuggerWork = 0; Process = NULL; if (AttachProcess || KillProcess) { for (Process = PsGetNextProcess (NULL); Process != NULL; Process = PsGetNextProcess (Process)) { if (&Process->Pcb == AttachProcess) { KeStackAttachProcess (AttachProcess, &ApcState); break; } if (&Process->Pcb == KillProcess) { PsTerminateProcess(Process, DBG_TERMINATE_PROCESS); PsQuitNextProcess (Process); return; } } } if (PageIn) { try { Data = ProbeAndReadUchar (PageIn); } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } } DbgBreakPointWithStatus(DBG_STATUS_WORKER); if (Process != NULL) { KeUnstackDetachProcess (&ApcState); PsQuitNextProcess (Process); } return; }
VOID NTAPI KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { CCHAR Cpu; PKTHREAD InitialThread; ULONG64 InitialStack; PKIPCR Pcr; /* HACK */ FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea; //FrLdrDbgPrint("Hello from KiSystemStartup!!!\n"); /* Save the loader block */ KeLoaderBlock = LoaderBlock; /* Get the current CPU number */ Cpu = KeNumberProcessors++; // FIXME /* LoaderBlock initialization for Cpu 0 */ if (Cpu == 0) { /* Set the initial stack, idle thread and process */ LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; LoaderBlock->Process = (ULONG_PTR)&KiInitialProcess.Pcb; LoaderBlock->Prcb = (ULONG_PTR)&KiInitialPcr.Prcb; } /* Get Pcr from loader block */ Pcr = CONTAINING_RECORD(LoaderBlock->Prcb, KIPCR, Prcb); /* Set the PRCB for this Processor */ KiProcessorBlock[Cpu] = &Pcr->Prcb; /* Align stack to 16 bytes */ LoaderBlock->KernelStack &= ~(16 - 1); /* Save the initial thread and stack */ InitialStack = LoaderBlock->KernelStack; // Checkme InitialThread = (PKTHREAD)LoaderBlock->Thread; /* Set us as the current process */ InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process; /* Initialize the PCR */ KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack); /* Initialize the CPU features */ KiInitializeCpu(Pcr); /* Initial setup for the boot CPU */ if (Cpu == 0) { /* Initialize the module list (ntos, hal, kdcom) */ KiInitModuleList(LoaderBlock); /* Setup the TSS descriptors and entries */ KiInitializeTss(Pcr->TssBase, InitialStack); /* Setup the IDT */ KeInitExceptions(); /* Initialize debugging system */ KdInitSystem(0, KeLoaderBlock); /* Check for break-in */ if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n", Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase); /* Acquire lock */ while (InterlockedBitTestAndSet64((PLONG64)&KiFreezeExecutionLock, 0)) { /* Loop until lock is free */ while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1); } /* Initialize the Processor with HAL */ HalInitializeProcessor(Cpu, KeLoaderBlock); /* Set processor as active */ KeActiveProcessors |= 1ULL << Cpu; /* Release lock */ InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0); /* Raise to HIGH_LEVEL */ KfRaiseIrql(HIGH_LEVEL); /* Machine specific kernel initialization */ if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock); /* Switch to new kernel stack and start kernel bootstrapping */ KiSwitchToBootStack(InitialStack & ~3); }
NTSTATUS Log_Print(LOG_LEVEL Level, LPCSTR pszFormat, ...) { NTSTATUS Status = STATUS_SUCCESS; LARGE_INTEGER SystemTime, LocalTime; TIME_FIELDS TimeFields; PLOG_COUNTED_STRING Line = NULL; va_list args; KIRQL Irql = KeGetCurrentIrql(); LPCSTR StrLevel = " :"; if (!LogFile) return STATUS_INVALID_DEVICE_STATE; if (Irql > DISPATCH_LEVEL) return STATUS_INVALID_LEVEL; KeQuerySystemTime(&SystemTime); ExSystemTimeToLocalTime(&SystemTime, &LocalTime); RtlTimeToTimeFields(&LocalTime, &TimeFields); Line = ExAllocatePoolWithTag(NonPagedPool, MAX_LOG_STRING_SIZE + FIELD_OFFSET(LOG_COUNTED_STRING, Data), LogAllocationTag); if (!Line) return STATUS_INSUFFICIENT_RESOURCES; switch (Level) { case LL_FATAL: #if DBG DbgBreakPointWithStatus(DBG_STATUS_FATAL); #endif StrLevel = "FATAL :"; break; case LL_ERROR: StrLevel = "ERROR :"; break; case LL_WARNING: StrLevel = "WARNING:"; break; case LL_INFO: StrLevel = "INFO :"; break; case LL_VERBOSE: StrLevel = "VERBOSE:"; break; case LL_DEBUG: StrLevel = "DEBUG :"; break; } Status = StringCbPrintfA(Line->Data, MAX_LOG_STRING_SIZE, "%04u.%02u.%02u %02u:%02u:%02u.%03u PR:0x%04X TH:0x%04X IL:%d %s ", TimeFields.Year, TimeFields.Month, TimeFields.Day, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds, (ULONG)PsGetCurrentProcessId() & 0xFFFF, (ULONG)PsGetCurrentThreadId() & 0xFFFF, (ULONG)Irql, StrLevel); if (SUCCEEDED(Status)) { va_start(args, pszFormat); Line->DataLength = (USHORT)strlen(Line->Data); Status = StringCbVPrintfA(Line->Data + Line->DataLength, MAX_LOG_STRING_SIZE - Line->DataLength, pszFormat, args); if (SUCCEEDED(Status)) { Line->DataLength = (USHORT)strlen(Line->Data); if (Irql != PASSIVE_LEVEL) { PIO_WORKITEM pWorkItem = IoAllocateWorkItem(LogDeviceObject); InterlockedIncrement(&LogScheduledPrints); IoQueueWorkItemEx(pWorkItem, Log_WriteWorker, DelayedWorkQueue, Line); Status = STATUS_PENDING; } else { Status = Log_WriteLine(Line); } } va_end(args); } if (Status != STATUS_PENDING) ExFreePoolWithTag(Line, LogAllocationTag); return Status; }
VOID NTAPI INIT_FUNCTION KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG Cpu; PKTHREAD InitialThread; ULONG InitialStack; PKGDTENTRY Gdt; PKIDTENTRY Idt; KIDTENTRY NmiEntry, DoubleFaultEntry; PKTSS Tss; PKIPCR Pcr; /* Boot cycles timestamp */ BootCycles = __rdtsc(); /* Save the loader block and get the current CPU */ KeLoaderBlock = LoaderBlock; Cpu = KeNumberProcessors; if (!Cpu) { /* If this is the boot CPU, set FS and the CPU Number*/ Ke386SetFs(KGDT_R0_PCR); __writefsdword(KPCR_PROCESSOR_NUMBER, Cpu); /* Set the initial stack and idle thread as well */ LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; } /* Save the initial thread and stack */ InitialStack = LoaderBlock->KernelStack; InitialThread = (PKTHREAD)LoaderBlock->Thread; /* Clean the APC List Head */ InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]); /* Initialize the machine type */ KiInitializeMachineType(); /* Skip initial setup if this isn't the Boot CPU */ if (Cpu) goto AppCpuInit; /* Get GDT, IDT, PCR and TSS pointers */ KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss); /* Setup the TSS descriptors and entries */ Ki386InitializeTss(Tss, Idt, Gdt); /* Initialize the PCR */ RtlZeroMemory(Pcr, PAGE_SIZE); KiInitializePcr(Cpu, Pcr, Idt, Gdt, Tss, InitialThread, (PVOID)KiDoubleFaultStack); /* Set us as the current process */ InitialThread->ApcState.Process = &KiInitialProcess.Pcb; /* Clear DR6/7 to cleanup bootloader debugging */ __writefsdword(KPCR_TEB, 0); __writefsdword(KPCR_DR6, 0); __writefsdword(KPCR_DR7, 0); /* Setup the IDT */ KeInitExceptions(); /* Load Ring 3 selectors for DS/ES */ Ke386SetDs(KGDT_R3_DATA | RPL_MASK); Ke386SetEs(KGDT_R3_DATA | RPL_MASK); /* Save NMI and double fault traps */ RtlCopyMemory(&NmiEntry, &Idt[2], sizeof(KIDTENTRY)); RtlCopyMemory(&DoubleFaultEntry, &Idt[8], sizeof(KIDTENTRY)); /* Copy kernel's trap handlers */ RtlCopyMemory(Idt, (PVOID)KiIdtDescriptor.Base, KiIdtDescriptor.Limit + 1); /* Restore NMI and double fault */ RtlCopyMemory(&Idt[2], &NmiEntry, sizeof(KIDTENTRY)); RtlCopyMemory(&Idt[8], &DoubleFaultEntry, sizeof(KIDTENTRY)); AppCpuInit: /* Loop until we can release the freeze lock */ do { /* Loop until execution can continue */ while (*(volatile PKSPIN_LOCK*)&KiFreezeExecutionLock == (PVOID)1); } while(InterlockedBitTestAndSet((PLONG)&KiFreezeExecutionLock, 0)); /* Setup CPU-related fields */ __writefsdword(KPCR_NUMBER, Cpu); __writefsdword(KPCR_SET_MEMBER, 1 << Cpu); __writefsdword(KPCR_SET_MEMBER_COPY, 1 << Cpu); __writefsdword(KPCR_PRCB_SET_MEMBER, 1 << Cpu); /* Initialize the Processor with HAL */ HalInitializeProcessor(Cpu, KeLoaderBlock); /* Set active processors */ KeActiveProcessors |= __readfsdword(KPCR_SET_MEMBER); KeNumberProcessors++; /* Check if this is the boot CPU */ if (!Cpu) { /* Initialize debugging system */ KdInitSystem(0, KeLoaderBlock); /* Check for break-in */ if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } /* Raise to HIGH_LEVEL */ KfRaiseIrql(HIGH_LEVEL); /* Switch to new kernel stack and start kernel bootstrapping */ KiSwitchToBootStack(InitialStack & ~3); }
NTSTATUS NtSystemDebugControl ( IN SYSDBG_COMMAND Command, IN PVOID InputBuffer, IN ULONG InputBufferLength, OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, OUT PULONG ReturnLength OPTIONAL ) /*++ Routine Description: This function controls the system debugger. Arguments: Command - The command to be executed. One of the following: SysDbgQueryTraceInformation SysDbgSetTracepoint SysDbgSetSpecialCall SysDbgClearSpecialCalls SysDbgQuerySpecialCalls InputBuffer - A pointer to a buffer describing the input data for the request, if any. The structure of this buffer varies depending upon Command. InputBufferLength - The length in bytes of InputBuffer. OutputBuffer - A pointer to a buffer that is to receive the output data for the request, if any. The structure of this buffer varies depending upon Command. OutputBufferLength - The length in bytes of OutputBuffer. ReturnLength - A optional pointer to a ULONG that is to receive the output data length for the request. Return Value: Returns one of the following status codes: STATUS_SUCCESS - normal, successful completion. STATUS_INVALID_INFO_CLASS - The Command parameter did not specify a valid value. STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the Parameters buffer was not correct. STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer or a pointer within the Parameters buffer specified an invalid address. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist for this request to complete. --*/ { NTSTATUS status = STATUS_SUCCESS; BOOLEAN releaseModuleResoure = FALSE; ULONG length = 0; KPROCESSOR_MODE PreviousMode; PreviousMode = KeGetPreviousMode(); if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) { return STATUS_ACCESS_DENIED; } // // Operate within a try block in order to catch errors. // try { // // Probe input and output buffers, if previous mode is not // kernel. // if ( PreviousMode != KernelMode ) { if ( InputBufferLength != 0 ) { ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) ); } if ( OutputBufferLength != 0 ) { ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) ); } if ( ARGUMENT_PRESENT(ReturnLength) ) { ProbeForWriteUlong( ReturnLength ); } } // // Switch on the command code. // switch ( Command ) { #ifdef _X86_ case SysDbgQueryTraceInformation: status = KdGetTraceInformation( OutputBuffer, OutputBufferLength, &length ); break; case SysDbgSetTracepoint: if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) { return STATUS_INFO_LENGTH_MISMATCH; } KdSetInternalBreakpoint( InputBuffer ); break; case SysDbgSetSpecialCall: if ( InputBufferLength != sizeof(PVOID) ) { return STATUS_INFO_LENGTH_MISMATCH; } KdSetSpecialCall( InputBuffer, NULL ); break; case SysDbgClearSpecialCalls: KdClearSpecialCalls( ); break; case SysDbgQuerySpecialCalls: status = KdQuerySpecialCalls( OutputBuffer, OutputBufferLength, &length ); break; #endif case SysDbgBreakPoint: if (KdDebuggerEnabled) { DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL); } else { status = STATUS_UNSUCCESSFUL; } break; default: // // Invalid Command. // status = STATUS_INVALID_INFO_CLASS; } if ( ARGUMENT_PRESENT(ReturnLength) ) { *ReturnLength = length; } } except ( EXCEPTION_EXECUTE_HANDLER ) { if ( releaseModuleResoure ) { ExReleaseResource( &PsLoadedModuleResource ); KeLeaveCriticalRegion(); } status = GetExceptionCode(); } return status; } // NtSystemDebugControl