2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdprint.c
5 * PURPOSE: KD64 Trap Handler Routines
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 KdpPrintString(IN PSTRING Output
)
23 DBGKD_DEBUG_IO DebugIo
;
24 USHORT Length
= Output
->Length
;
27 RtlMoveMemory(KdpMessageBuffer
, Output
->Buffer
, Length
);
29 /* Make sure we don't exceed the KD Packet size */
30 if ((sizeof(DBGKD_DEBUG_IO
) + Length
) > PACKET_MAX_SIZE
)
32 /* Normalize length */
33 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_DEBUG_IO
);
36 /* Build the packet header */
37 DebugIo
.ApiNumber
= DbgKdPrintStringApi
;
38 DebugIo
.ProcessorLevel
= KeProcessorLevel
;
39 DebugIo
.Processor
= KeGetCurrentPrcb()->Number
;
40 DebugIo
.u
.PrintString
.LengthOfString
= Length
;
41 Header
.Length
= sizeof(DBGKD_DEBUG_IO
);
42 Header
.Buffer
= (PCHAR
)&DebugIo
;
46 Data
.Buffer
= KdpMessageBuffer
;
49 KdSendPacket(PACKET_TYPE_KD_DEBUG_IO
, &Header
, &Data
, &KdpContext
);
51 /* Check if the user pressed CTRL+C */
52 return KdpPollBreakInWithPortLock();
57 KdpPromptString(IN PSTRING PromptString
,
58 IN PSTRING ResponseString
)
61 DBGKD_DEBUG_IO DebugIo
;
62 ULONG Length
= PromptString
->Length
;
65 /* Copy the string to the message buffer */
66 RtlCopyMemory(KdpMessageBuffer
,
68 PromptString
->Length
);
70 /* Make sure we don't exceed the KD Packet size */
71 if ((sizeof(DBGKD_DEBUG_IO
) + Length
) > PACKET_MAX_SIZE
)
73 /* Normalize length */
74 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_DEBUG_IO
);
77 /* Build the packet header */
78 DebugIo
.ApiNumber
= DbgKdGetStringApi
;
79 DebugIo
.ProcessorLevel
= KeProcessorLevel
;
80 DebugIo
.Processor
= KeGetCurrentPrcb()->Number
;
81 DebugIo
.u
.GetString
.LengthOfPromptString
= Length
;
82 DebugIo
.u
.GetString
.LengthOfStringRead
= ResponseString
->MaximumLength
;
83 Header
.Length
= sizeof(DBGKD_DEBUG_IO
);
84 Header
.Buffer
= (PCHAR
)&DebugIo
;
87 Data
.Length
= PromptString
->Length
;
88 Data
.Buffer
= KdpMessageBuffer
;
91 KdSendPacket(PACKET_TYPE_KD_DEBUG_IO
, &Header
, &Data
, &KdpContext
);
93 /* Set the maximum lengths for the receive */
94 Header
.MaximumLength
= sizeof(DBGKD_DEBUG_IO
);
95 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
97 /* Enter receive loop */
101 Status
= KdReceivePacket(PACKET_TYPE_KD_DEBUG_IO
,
107 /* Return TRUE if we need to resend */
108 if (Status
== KdPacketNeedsResend
) return TRUE
;
110 /* Loop until we succeed */
111 } while (Status
!= KdPacketReceived
);
113 /* Don't copy back a larger respone than there is room foor */
114 Length
= min(Length
, ResponseString
->MaximumLength
);
116 /* Copy back the string and return the length */
117 RtlCopyMemory(ResponseString
->Buffer
, KdpMessageBuffer
, Length
);
118 ResponseString
->Length
= Length
;
120 /* Success; we don't need to resend */
126 KdpCommandString(IN ULONG Length
,
128 IN KPROCESSOR_MODE PreviousMode
,
129 IN PCONTEXT ContextRecord
,
130 IN PKTRAP_FRAME TrapFrame
,
131 IN PKEXCEPTION_FRAME ExceptionFrame
)
134 KdpDprintf("KdpCommandString called\n");
140 KdpSymbol(IN PSTRING DllPath
,
141 IN PKD_SYMBOLS_INFO DllBase
,
143 IN KPROCESSOR_MODE PreviousMode
,
144 IN PCONTEXT ContextRecord
,
145 IN PKTRAP_FRAME TrapFrame
,
146 IN PKEXCEPTION_FRAME ExceptionFrame
)
149 PKPRCB Prcb
= KeGetCurrentPrcb();
152 /* Check if we need to do anything */
153 if ((PreviousMode
!= KernelMode
) || (KdDebuggerNotPresent
)) return;
155 /* Enter the debugger */
156 Entered
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
158 /* Save the CPU Control State and save the context */
159 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
160 RtlCopyMemory(&Prcb
->ProcessorState
.ContextFrame
,
164 /* Report the new state */
165 Status
= KdpReportLoadSymbolsStateChange(DllPath
,
168 &Prcb
->ProcessorState
.
171 /* Now restore the processor state, manually again. */
172 RtlCopyMemory(ContextRecord
,
173 &Prcb
->ProcessorState
.ContextFrame
,
175 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
177 /* Exit the debugger and clear the CTRL-C state */
178 KdExitDebugger(Entered
);
183 KdpPrompt(IN LPSTR PromptString
,
184 IN USHORT PromptLength
,
185 OUT LPSTR ResponseString
,
186 IN USHORT MaximumResponseLength
,
187 IN KPROCESSOR_MODE PreviousMode
,
188 IN PKTRAP_FRAME TrapFrame
,
189 IN PKEXCEPTION_FRAME ExceptionFrame
)
191 STRING PromptBuffer
, ResponseBuffer
;
192 BOOLEAN Entered
, Resend
;
194 /* Normalize the lengths */
195 PromptLength
= min(PromptLength
, 512);
196 MaximumResponseLength
= min(MaximumResponseLength
, 512);
198 /* Check if we need to verify the string */
199 if (PreviousMode
!= KernelMode
)
201 /* FIXME: Handle user-mode */
204 /* Setup the prompt and response buffers */
205 PromptBuffer
.Buffer
= PromptString
;
206 PromptBuffer
.Length
= PromptLength
;
207 ResponseBuffer
.Buffer
= ResponseString
;
208 ResponseBuffer
.Length
= 0;
209 ResponseBuffer
.MaximumLength
= MaximumResponseLength
;
212 //KdLogDbgPrint(&PromptBuffer);
214 /* Enter the debugger */
215 Entered
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
217 /* Enter prompt loop */
220 /* Send the prompt and receive the response */
221 Resend
= KdpPromptString(&PromptBuffer
, &ResponseBuffer
);
223 /* Loop while we need to resend */
226 /* Exit the debugger */
227 KdExitDebugger(Entered
);
229 /* Return the number of characters received */
230 return ResponseBuffer
.Length
;
235 KdpPrint(IN ULONG ComponentId
,
236 IN ULONG ComponentMask
,
239 IN KPROCESSOR_MODE PreviousMode
,
240 IN PKTRAP_FRAME TrapFrame
,
241 IN PKEXCEPTION_FRAME ExceptionFrame
,
244 NTSTATUS ReturnStatus
;
246 ANSI_STRING AnsiString
;
251 /* Validate the mask */
252 if (ComponentMask
< 0x20) ComponentMask
= 1 << ComponentMask
;
253 if (!(Kd_WIN2000_Mask
& ComponentMask
) ||
254 ((ComponentId
< KdComponentTableSize
) &&
255 !(*KdComponentTable
[ComponentId
] & ComponentMask
)))
257 /* Mask validation failed */
262 /* Normalize the length */
263 Length
= min(Length
, 512);
265 /* Check if we need to verify the buffer */
266 if (PreviousMode
!= KernelMode
)
268 /* FIXME: Support user-mode */
271 /* Setup the ANSI string */
272 AnsiString
.Buffer
= String
;
273 AnsiString
.Length
= Length
;
276 //KdLogDbgPrint(&AnsiString);
278 /* Check for a debugger */
279 if (KdDebuggerNotPresent
)
283 return STATUS_DEVICE_NOT_CONNECTED
;
286 /* Enter the debugger */
287 Entered
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
289 /* Print the string */
290 if (KdpPrintString(&AnsiString
))
292 /* User pressed CTRL-C, breakpoint on return */
293 ReturnStatus
= STATUS_BREAKPOINT
;
297 /* String was printed */
298 ReturnStatus
= STATUS_SUCCESS
;
301 /* Exit the debugger and return */
302 KdExitDebugger(Entered
);
309 KdpDprintf(IN PCHAR Format
,
317 /* Format the string */
318 va_start(ap
, Format
);
319 Length
= (USHORT
)_vsnprintf(Buffer
,
325 String
.Buffer
= Buffer
;
326 String
.Length
= Length
+ 1;
328 /* Send it to the debugger directly */
329 KdpPrintString(&String
);