VOID KdpSetStateChange ( IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN BOOLEAN SecondChance ) /*++ Routine Description: Fill in the Wait_State_Change message record. Arguments: WaitStateChange - Supplies pointer to record to fill in ExceptionRecord - Supplies a pointer to an exception record. ContextRecord - Supplies a pointer to a context record. SecondChance - Supplies a boolean value that determines whether this is the first or second chance for the exception. Return Value: None. --*/ { BOOLEAN status; // // Set up description of event, including exception record // WaitStateChange->NewState = DbgKdExceptionStateChange; WaitStateChange->ProcessorLevel = KeProcessorLevel; WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number; WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors; WaitStateChange->Thread = (PVOID)KeGetCurrentThread(); WaitStateChange->ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord); KdpQuickMoveMemory( (PCHAR)&WaitStateChange->u.Exception.ExceptionRecord, (PCHAR)ExceptionRecord, sizeof(EXCEPTION_RECORD) ); WaitStateChange->u.Exception.FirstChance = !SecondChance; // // Copy instruction stream immediately following location of event // WaitStateChange->ControlReport.InstructionCount = KdpMoveMemory( &(WaitStateChange->ControlReport.InstructionStream[0]), WaitStateChange->ProgramCounter, DBGKD_MAXSTREAM ); // // Copy context record immediately following instruction stream // if (KdpSendContext) { KdpMoveMemory((PCHAR)&WaitStateChange->Context, (PCHAR)ContextRecord, sizeof(*ContextRecord)); } // // Clear breakpoints in copied area // status = KdpDeleteBreakpointRange( WaitStateChange->ProgramCounter, (PVOID)((PUCHAR)WaitStateChange->ProgramCounter + WaitStateChange->ControlReport.InstructionCount - 1) ); // // If there were any breakpoints cleared, recopy the area without them // if (status == TRUE) { KdpMoveMemory( &(WaitStateChange->ControlReport.InstructionStream[0]), WaitStateChange->ProgramCounter, WaitStateChange->ControlReport.InstructionCount ); } }
VOID KdpSetStateChange ( IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange, IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN BOOLEAN SecondChance ) /*++ Routine Description: Fill in the Wait_State_Change message record. Arguments: WaitStateChange - Supplies pointer to record to fill in ExceptionRecord - Supplies a pointer to an exception record. ContextRecord - Supplies a pointer to a context record. SecondChance - Supplies a boolean value that determines whether this is the first or second chance for the exception. Return Value: None. --*/ { ULONG Count; PVOID End; // // Set up description of event, including exception record // WaitStateChange->NewState = DbgKdExceptionStateChange; WaitStateChange->ProcessorLevel = KeProcessorLevel; WaitStateChange->Processor = (USHORT)KdpGetCurrentPrcb()->Number; WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors; WaitStateChange->Thread = (ULONG_PTR)KdpGetCurrentThread(); WaitStateChange->ProgramCounter = (ULONG_PTR)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord); if (sizeof(EXCEPTION_RECORD) == sizeof(WaitStateChange->u.Exception.ExceptionRecord)) { KdpQuickMoveMemory((PCHAR)&WaitStateChange->u.Exception.ExceptionRecord, (PCHAR)ExceptionRecord, sizeof(EXCEPTION_RECORD)); } else { ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord, &WaitStateChange->u.Exception.ExceptionRecord ); } WaitStateChange->u.Exception.FirstChance = !SecondChance; // // Copy the immediate instruction stream into the control report structure. // Count = KdpMoveMemory(&WaitStateChange->ControlReport.InstructionStream[0], (PVOID)WaitStateChange->ProgramCounter, DBGKD_MAXSTREAM); WaitStateChange->ControlReport.InstructionCount = (USHORT)Count; // // Clear breakpoints in the copied instruction stream. If any breakpoints // are clear, then recopy the instruction strasm. // End = (PVOID)((PUCHAR)(WaitStateChange->ProgramCounter) + Count - 1); if (KdpDeleteBreakpointRange((PVOID)WaitStateChange->ProgramCounter, End) != FALSE) { KdpMoveMemory(&WaitStateChange->ControlReport.InstructionStream[0], (PVOID)WaitStateChange->ProgramCounter, Count); } // // Copy the context record into the wait state structure. // KdpMoveMemory((PCHAR)&WaitStateChange->Context, (PCHAR)ContextRecord, sizeof(*ContextRecord)); return; }
VOID KiFreezeTargetExecution ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function freezes the execution of the current running processor. If a trapframe is supplied to current state is saved into the prcb for the debugger. Arguments: TrapFrame - Supplies a pointer to the trap frame that describes the trap. ExceptionFrame - Supplies a pointer to the exception frame that describes the trap. Return Value: None. --*/ { #if !defined(NT_UP) KIRQL OldIrql; PKPRCB Prcb; BOOLEAN Enable; KCONTINUE_STATUS Status; EXCEPTION_RECORD ExceptionRecord; Enable = KiDisableInterrupts(); KeRaiseIrql(HIGH_LEVEL, &OldIrql); Prcb = KeGetCurrentPrcb(); Prcb->IpiFrozen = TARGET_FROZEN; Prcb->SkipTick = TRUE; if (TrapFrame != NULL) { KiSaveProcessorState(TrapFrame, ExceptionFrame); } // // Sweep the data cache in case this is a system crash and the bug // check code is attempting to write a crash dump file. // KeSweepCurrentDcache(); // // Wait for person requesting us to freeze to // clear our frozen flag // while (FrozenState(Prcb->IpiFrozen) == TARGET_FROZEN) { if (Prcb->IpiFrozen & FREEZE_ACTIVE) { // // This processor has been made the active processor // if (TrapFrame) { RtlZeroMemory (&ExceptionRecord, sizeof ExceptionRecord); ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER; ExceptionRecord.ExceptionRecord = &ExceptionRecord; ExceptionRecord.ExceptionAddress = (PVOID)CONTEXT_TO_PROGRAM_COUNTER (&Prcb->ProcessorState.ContextFrame); Status = (KiDebugSwitchRoutine) ( &ExceptionRecord, &Prcb->ProcessorState.ContextFrame, FALSE ); } else { Status = ContinueError; } // // If status is anything other then, continue with next // processor then reselect master // if (Status != ContinueNextProcessor) { Prcb->IpiFrozen &= ~FREEZE_ACTIVE; KiFreezeOwner->IpiFrozen |= FREEZE_ACTIVE; } } KeYieldProcessor(); } if (TrapFrame != NULL) { KiRestoreProcessorState(TrapFrame, ExceptionFrame); } Prcb->IpiFrozen = RUNNING; KeFlushCurrentTb(); KeSweepCurrentIcache(); KeLowerIrql(OldIrql); KiRestoreInterrupts(Enable); #endif // !define(NT_UP) return; }
VOID SetThreadFields( PSYSTEM_THREAD_INFORMATION ThreadInfo, HWND hwnd ) { TIME_FIELDS UserTime; TIME_FIELDS KernelTime; TIME_FIELDS RunTime; LARGE_INTEGER Time; CHAR TimeString[15]; CHAR StartString[32]; HANDLE hThread; CONTEXT ThreadContext; NTSTATUS Status; OBJECT_ATTRIBUTES Obja; ULONG PcValue; // // Display the selected thread information // // // Compute runtimes // RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime); RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime); RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime); RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime); Time.QuadPart = RefreshTimeOfDayInfo.CurrentTime.QuadPart - ThreadInfo->CreateTime.QuadPart; RtlTimeToTimeFields ( &Time, &RunTime); wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld", RunTime.Hour, RunTime.Minute, RunTime.Second, RunTime.Milliseconds ); SetDlgItemText( hwnd, PXPLODE_THREADELAPSED_TIME, TimeString ); wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld", UserTime.Hour, UserTime.Minute, UserTime.Second, UserTime.Milliseconds ); SetDlgItemText( hwnd, PXPLODE_THREADUSER_TIME, TimeString ); wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld", KernelTime.Hour, KernelTime.Minute, KernelTime.Second, KernelTime.Milliseconds ); SetDlgItemText( hwnd, PXPLODE_THREADKERNEL_TIME, TimeString ); wsprintf(StartString,"0x%08lx", ThreadInfo->StartAddress ); SetDlgItemText( hwnd, PXPLODE_THREAD_START, StartString ); // // Do the priority Group // SetDlgItemInt( hwnd, PXPLODE_THREAD_DYNAMIC, ThreadInfo->Priority, FALSE ); switch ( ThreadInfo->BasePriority - DlgProcessInfo->BasePriority ) { case 2: CheckRadioButton( hwnd, PXPLODE_THREAD_HIGHEST, PXPLODE_THREAD_LOWEST, PXPLODE_THREAD_HIGHEST ); break; case 1: CheckRadioButton( hwnd, PXPLODE_THREAD_HIGHEST, PXPLODE_THREAD_LOWEST, PXPLODE_THREAD_ABOVE ); break; case -1: CheckRadioButton( hwnd, PXPLODE_THREAD_HIGHEST, PXPLODE_THREAD_LOWEST, PXPLODE_THREAD_BELOW ); break; case -2: CheckRadioButton( hwnd, PXPLODE_THREAD_HIGHEST, PXPLODE_THREAD_LOWEST, PXPLODE_THREAD_LOWEST ); break; case 0: default: CheckRadioButton( hwnd, PXPLODE_THREAD_HIGHEST, PXPLODE_THREAD_LOWEST, PXPLODE_THREAD_NORMAL ); break; } // // Complete thread information // SetDlgItemInt( hwnd, PXPLODE_THREAD_SWITCHES, ThreadInfo->ContextSwitches, FALSE ); PcValue = 0; InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL); Status = NtOpenThread( &hThread, THREAD_GET_CONTEXT, &Obja, &ThreadInfo->ClientId ); if ( NT_SUCCESS(Status) ) { ThreadContext.ContextFlags = CONTEXT_CONTROL; Status = NtGetContextThread(hThread,&ThreadContext); NtClose(hThread); if ( NT_SUCCESS(Status) ) { PcValue = (ULONG) CONTEXT_TO_PROGRAM_COUNTER(&ThreadContext); } } if ( PcValue ) { wsprintf(StartString,"0x%08lx", PcValue ); SetDlgItemText( hwnd, PXPLODE_THREAD_PC, StartString ); } else { SetDlgItemText( hwnd, PXPLODE_THREAD_PC, "Unknown" ); } // // Disable the thread buttons if we can't get at the thread or it's token // { HANDLE Thread; HANDLE Token; BOOL ThreadOK = FALSE; BOOL GotToken = FALSE; Thread = OpenThread(MAXIMUM_ALLOWED, FALSE, (DWORD)ThreadInfo->ClientId.UniqueThread); if (Thread != NULL) { ThreadOK = TRUE; if (OpenThreadToken(Thread, MAXIMUM_ALLOWED, TRUE, &Token)) { GotToken = TRUE; CloseHandle(Token); } CloseHandle(Thread); } EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_ACL), ThreadOK); EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN), GotToken); EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN_ACL), GotToken); } }