306 lines
6.5 KiB
C
306 lines
6.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
kddbgio.c
|
||
|
||
Abstract:
|
||
|
||
This module implements kernel debugger based Dbg I/O. This
|
||
is the foundation for DbgPrint and DbgPrompt.
|
||
|
||
Author:
|
||
|
||
Mark Lucovsky (markl) 31-Aug-1990
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "kdp.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGEKD, KdpPrintString)
|
||
#pragma alloc_text(PAGEKD, KdpPromptString)
|
||
#pragma alloc_text(PAGEKD, KdpAcquireBreakpoint)
|
||
#endif
|
||
|
||
BOOLEAN
|
||
KdpPrintString (
|
||
IN PSTRING Output
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine prints a string.
|
||
|
||
Arguments:
|
||
|
||
Output - Supplies a pointer to a string descriptor for the output string.
|
||
|
||
Return Value:
|
||
|
||
TRUE if Control-C present in input buffer after print is done.
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Length;
|
||
STRING MessageData;
|
||
STRING MessageHeader;
|
||
DBGKD_DEBUG_IO DebugIo;
|
||
|
||
//
|
||
// Move the output string to the message buffer.
|
||
//
|
||
|
||
KdpCopyFromPtr(KdpMessageBuffer,
|
||
Output->Buffer,
|
||
Output->Length,
|
||
&Length);
|
||
|
||
//
|
||
// If the total message length is greater than the maximum packet size,
|
||
// then truncate the output string.
|
||
//
|
||
|
||
if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE) {
|
||
Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO);
|
||
}
|
||
|
||
//
|
||
// Construct the print string message and message descriptor.
|
||
//
|
||
|
||
DebugIo.ApiNumber = DbgKdPrintStringApi;
|
||
DebugIo.ProcessorLevel = KeProcessorLevel;
|
||
DebugIo.Processor = (USHORT)KeGetCurrentPrcb()->Number;
|
||
DebugIo.u.PrintString.LengthOfString = Length;
|
||
MessageHeader.Length = sizeof(DBGKD_DEBUG_IO);
|
||
MessageHeader.Buffer = (PCHAR)&DebugIo;
|
||
|
||
//
|
||
// Construct the print string data and data descriptor.
|
||
//
|
||
|
||
MessageData.Length = (USHORT)Length;
|
||
MessageData.Buffer = KdpMessageBuffer;
|
||
|
||
//
|
||
// Send packet to the kernel debugger on the host machine.
|
||
//
|
||
|
||
KdSendPacket(
|
||
PACKET_TYPE_KD_DEBUG_IO,
|
||
&MessageHeader,
|
||
&MessageData,
|
||
&KdpContext
|
||
);
|
||
|
||
return KdpPollBreakInWithPortLock();
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
KdpPromptString (
|
||
IN PSTRING Output,
|
||
IN OUT PSTRING Input
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine prints a string, then reads a reply string.
|
||
|
||
Arguments:
|
||
|
||
Output - Supplies a pointer to a string descriptor for the output string.
|
||
|
||
Input - Supplies a pointer to a string descriptor for the input string.
|
||
(Length stored/returned in Input->Length)
|
||
|
||
Return Value:
|
||
|
||
TRUE - A Breakin sequence was seen, caller should breakpoint and retry
|
||
FALSE - No Breakin seen.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Length;
|
||
STRING MessageData;
|
||
STRING MessageHeader;
|
||
DBGKD_DEBUG_IO DebugIo;
|
||
ULONG ReturnCode;
|
||
|
||
//
|
||
// Move the output string to the message buffer.
|
||
//
|
||
|
||
KdpCopyFromPtr(KdpMessageBuffer,
|
||
Output->Buffer,
|
||
Output->Length,
|
||
&Length);
|
||
|
||
//
|
||
// If the total message length is greater than the maximum packet size,
|
||
// then truncate the output string.
|
||
//
|
||
|
||
if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE) {
|
||
Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO);
|
||
}
|
||
|
||
//
|
||
// Construct the prompt string message and message descriptor.
|
||
//
|
||
|
||
DebugIo.ApiNumber = DbgKdGetStringApi;
|
||
DebugIo.ProcessorLevel = KeProcessorLevel;
|
||
DebugIo.Processor = (USHORT)KeGetCurrentPrcb()->Number;
|
||
DebugIo.u.GetString.LengthOfPromptString = Length;
|
||
DebugIo.u.GetString.LengthOfStringRead = Input->MaximumLength;
|
||
MessageHeader.Length = sizeof(DBGKD_DEBUG_IO);
|
||
MessageHeader.Buffer = (PCHAR)&DebugIo;
|
||
|
||
//
|
||
// Construct the prompt string data and data descriptor.
|
||
//
|
||
|
||
MessageData.Length = (USHORT)Length;
|
||
MessageData.Buffer = KdpMessageBuffer;
|
||
|
||
//
|
||
// Send packet to the kernel debugger on the host machine.
|
||
//
|
||
|
||
KdSendPacket(
|
||
PACKET_TYPE_KD_DEBUG_IO,
|
||
&MessageHeader,
|
||
&MessageData,
|
||
&KdpContext
|
||
);
|
||
|
||
|
||
//
|
||
// Receive packet from the kernel debugger on the host machine.
|
||
//
|
||
|
||
MessageHeader.MaximumLength = sizeof(DBGKD_DEBUG_IO);
|
||
MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
|
||
|
||
do {
|
||
ReturnCode = KdReceivePacket(
|
||
PACKET_TYPE_KD_DEBUG_IO,
|
||
&MessageHeader,
|
||
&MessageData,
|
||
&Length,
|
||
&KdpContext
|
||
);
|
||
if (ReturnCode == KDP_PACKET_RESEND) {
|
||
return TRUE;
|
||
}
|
||
} while (ReturnCode != KDP_PACKET_RECEIVED);
|
||
|
||
|
||
if (Length > Input->MaximumLength) {
|
||
Length = Input->MaximumLength;
|
||
}
|
||
|
||
KdpCopyToPtr(Input->Buffer,
|
||
KdpMessageBuffer,
|
||
Length,
|
||
&Length);
|
||
Input->Length = (USHORT)Length;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
BOOLEAN
|
||
KdpAcquireBreakpoint(
|
||
IN ULONG Number
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine prints a string, then reads a reply string.
|
||
|
||
Arguments:
|
||
|
||
Number - breakpoint register number being requested.
|
||
|
||
Return Value:
|
||
|
||
TRUE - Breakpoint now reserved for kernel use.
|
||
FALSE - breakpoint not available.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Length;
|
||
STRING MessageData;
|
||
STRING MessageHeader;
|
||
DBGKD_CONTROL_REQUEST ControlRequest;
|
||
ULONG ReturnCode;
|
||
|
||
//
|
||
// Construct the prompt string message and message descriptor.
|
||
//
|
||
|
||
ControlRequest.ApiNumber = DbgKdRequestHardwareBp;
|
||
ControlRequest.u.RequestBreakpoint.HardwareBreakPointNumber = Number;
|
||
ControlRequest.u.RequestBreakpoint.Available = FALSE;
|
||
MessageHeader.Length = sizeof(ControlRequest);
|
||
MessageHeader.Buffer = (PCHAR)&ControlRequest;
|
||
|
||
//
|
||
// Send packet to the kernel debugger on the host machine.
|
||
//
|
||
|
||
KdSendPacket(PACKET_TYPE_KD_CONTROL_REQUEST,
|
||
&MessageHeader,
|
||
NULL,
|
||
&KdpContext);
|
||
|
||
//
|
||
// Receive packet from the kernel debugger on the host machine.
|
||
//
|
||
|
||
MessageHeader.MaximumLength = sizeof(PACKET_TYPE_KD_CONTROL_REQUEST);
|
||
|
||
MessageData.Buffer = KdpMessageBuffer;
|
||
MessageData.Length = 0;
|
||
MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE;
|
||
|
||
do
|
||
{
|
||
ReturnCode = KdReceivePacket(PACKET_TYPE_KD_CONTROL_REQUEST,
|
||
&MessageHeader,
|
||
&MessageData,
|
||
&Length,
|
||
&KdpContext);
|
||
|
||
if (ReturnCode == KDP_PACKET_RESEND)
|
||
{
|
||
return FALSE;
|
||
}
|
||
} while (ReturnCode != KDP_PACKET_RECEIVED);
|
||
|
||
return (ControlRequest.u.RequestBreakpoint.Available == 1);
|
||
}
|