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
= (USHORT
)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
= (USHORT
)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 response than there is room for */
114 Length
= min(Length
, ResponseString
->MaximumLength
);
116 /* Copy back the string and return the length */
117 RtlCopyMemory(ResponseString
->Buffer
, KdpMessageBuffer
, Length
);
118 ResponseString
->Length
= (USHORT
)Length
;
120 /* Success; we don't need to resend */
126 KdpCommandString(IN PSTRING NameString
,
127 IN PSTRING CommandString
,
128 IN KPROCESSOR_MODE PreviousMode
,
129 IN PCONTEXT ContextRecord
,
130 IN PKTRAP_FRAME TrapFrame
,
131 IN PKEXCEPTION_FRAME ExceptionFrame
)
134 PKPRCB Prcb
= KeGetCurrentPrcb();
136 /* Check if we need to do anything */
137 if ((PreviousMode
!= KernelMode
) || (KdDebuggerNotPresent
)) return;
139 /* Enter the debugger */
140 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
142 /* Save the CPU Control State and save the context */
143 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
144 RtlCopyMemory(&Prcb
->ProcessorState
.ContextFrame
,
148 /* Send the command string to the debugger */
149 KdpReportCommandStringStateChange(NameString
,
151 &Prcb
->ProcessorState
.ContextFrame
);
153 /* Restore the processor state */
154 RtlCopyMemory(ContextRecord
,
155 &Prcb
->ProcessorState
.ContextFrame
,
157 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
159 /* Exit the debugger and return */
160 KdExitDebugger(Enable
);
165 KdpSymbol(IN PSTRING DllPath
,
166 IN PKD_SYMBOLS_INFO SymbolInfo
,
168 IN KPROCESSOR_MODE PreviousMode
,
169 IN PCONTEXT ContextRecord
,
170 IN PKTRAP_FRAME TrapFrame
,
171 IN PKEXCEPTION_FRAME ExceptionFrame
)
174 PKPRCB Prcb
= KeGetCurrentPrcb();
176 /* Check if we need to do anything */
177 if ((PreviousMode
!= KernelMode
) || (KdDebuggerNotPresent
)) return;
179 /* Enter the debugger */
180 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
182 /* Save the CPU Control State and save the context */
183 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
184 RtlCopyMemory(&Prcb
->ProcessorState
.ContextFrame
,
188 /* Report the new state */
189 KdpReportLoadSymbolsStateChange(DllPath
,
192 &Prcb
->ProcessorState
.ContextFrame
);
194 /* Restore the processor state */
195 RtlCopyMemory(ContextRecord
,
196 &Prcb
->ProcessorState
.ContextFrame
,
198 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
200 /* Exit the debugger and return */
201 KdExitDebugger(Enable
);
206 KdpPrompt(IN LPSTR PromptString
,
207 IN USHORT PromptLength
,
208 OUT LPSTR ResponseString
,
209 IN USHORT MaximumResponseLength
,
210 IN KPROCESSOR_MODE PreviousMode
,
211 IN PKTRAP_FRAME TrapFrame
,
212 IN PKEXCEPTION_FRAME ExceptionFrame
)
214 STRING PromptBuffer
, ResponseBuffer
;
215 BOOLEAN Enable
, Resend
;
217 /* Normalize the lengths */
218 PromptLength
= min(PromptLength
, 512);
219 MaximumResponseLength
= min(MaximumResponseLength
, 512);
221 /* Check if we need to verify the string */
222 if (PreviousMode
!= KernelMode
)
224 /* FIXME: Handle user-mode */
227 /* Setup the prompt and response buffers */
228 PromptBuffer
.Buffer
= PromptString
;
229 PromptBuffer
.Length
= PromptLength
;
230 ResponseBuffer
.Buffer
= ResponseString
;
231 ResponseBuffer
.Length
= 0;
232 ResponseBuffer
.MaximumLength
= MaximumResponseLength
;
235 //KdLogDbgPrint(&PromptBuffer);
237 /* Enter the debugger */
238 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
240 /* Enter prompt loop */
243 /* Send the prompt and receive the response */
244 Resend
= KdpPromptString(&PromptBuffer
, &ResponseBuffer
);
246 /* Loop while we need to resend */
249 /* Exit the debugger */
250 KdExitDebugger(Enable
);
252 /* Return the number of characters received */
253 return ResponseBuffer
.Length
;
258 KdpPrint(IN ULONG ComponentId
,
262 IN KPROCESSOR_MODE PreviousMode
,
263 IN PKTRAP_FRAME TrapFrame
,
264 IN PKEXCEPTION_FRAME ExceptionFrame
,
265 OUT PBOOLEAN Handled
)
267 NTSTATUS ReturnStatus
;
274 /* Validate the mask */
275 if (Level
< 32) Level
= 1 << Level
;
276 if (!(Kd_WIN2000_Mask
& Level
) ||
277 ((ComponentId
< KdComponentTableSize
) &&
278 !(*KdComponentTable
[ComponentId
] & Level
)))
280 /* Mask validation failed */
282 return STATUS_SUCCESS
;
285 /* Normalize the length */
286 Length
= min(Length
, 512);
288 /* Check if we need to verify the buffer */
289 if (PreviousMode
!= KernelMode
)
291 /* FIXME: Support user-mode */
294 /* Setup the output string */
295 OutputString
.Buffer
= String
;
296 OutputString
.Length
= Length
;
299 //KdLogDbgPrint(&OutputString);
301 /* Check for a debugger */
302 if (KdDebuggerNotPresent
)
306 return STATUS_DEVICE_NOT_CONNECTED
;
309 /* Enter the debugger */
310 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
312 /* Print the string */
313 if (KdpPrintString(&OutputString
))
315 /* User pressed CTRL-C, breakpoint on return */
316 ReturnStatus
= STATUS_BREAKPOINT
;
320 /* String was printed */
321 ReturnStatus
= STATUS_SUCCESS
;
324 /* Exit the debugger and return */
325 KdExitDebugger(Enable
);
332 KdpDprintf(IN PCHAR Format
,
340 /* Format the string */
341 va_start(ap
, Format
);
342 Length
= (USHORT
)_vsnprintf(Buffer
,
348 String
.Buffer
= Buffer
;
349 String
.Length
= Length
+ 1;
351 /* Send it to the debugger directly */
352 KdpPrintString(&String
);