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
;
216 PVOID CapturedPrompt
, CapturedResponse
;
218 /* Normalize the lengths */
219 PromptLength
= min(PromptLength
, 512);
220 MaximumResponseLength
= min(MaximumResponseLength
, 512);
222 /* Check if we need to verify the string */
223 if (PreviousMode
!= KernelMode
)
225 /* Capture user-mode buffers */
228 ProbeForRead(PromptString
, PromptLength
, 1);
229 CapturedPrompt
= alloca(512);
230 RtlMoveMemory(CapturedPrompt
, PromptString
, PromptLength
);
231 PromptString
= CapturedPrompt
;
233 ProbeForWrite(ResponseString
, MaximumResponseLength
, 1);
234 CapturedResponse
= alloca(512);
236 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
238 _SEH2_YIELD(return 0);
244 CapturedResponse
= ResponseString
;
247 /* Setup the prompt and response buffers */
248 PromptBuffer
.Buffer
= PromptString
;
249 PromptBuffer
.Length
= PromptLength
;
250 ResponseBuffer
.Buffer
= CapturedResponse
;
251 ResponseBuffer
.Length
= 0;
252 ResponseBuffer
.MaximumLength
= MaximumResponseLength
;
255 //KdLogDbgPrint(&PromptBuffer);
257 /* Enter the debugger */
258 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
260 /* Enter prompt loop */
263 /* Send the prompt and receive the response */
264 Resend
= KdpPromptString(&PromptBuffer
, &ResponseBuffer
);
266 /* Loop while we need to resend */
269 /* Exit the debugger */
270 KdExitDebugger(Enable
);
272 /* Copy back response if required */
273 if (PreviousMode
!= KernelMode
)
277 RtlMoveMemory(ResponseString
, ResponseBuffer
.Buffer
, ResponseBuffer
.Length
);
279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
281 _SEH2_YIELD(return 0);
286 /* Return the number of characters received */
287 return ResponseBuffer
.Length
;
292 KdpPrint(IN ULONG ComponentId
,
296 IN KPROCESSOR_MODE PreviousMode
,
297 IN PKTRAP_FRAME TrapFrame
,
298 IN PKEXCEPTION_FRAME ExceptionFrame
,
299 OUT PBOOLEAN Handled
)
301 NTSTATUS ReturnStatus
;
304 PVOID CapturedString
;
309 /* Validate the mask */
310 if (Level
< 32) Level
= 1 << Level
;
311 if (!(Kd_WIN2000_Mask
& Level
) ||
312 ((ComponentId
< KdComponentTableSize
) &&
313 !(*KdComponentTable
[ComponentId
] & Level
)))
315 /* Mask validation failed */
317 return STATUS_SUCCESS
;
320 /* Normalize the length */
321 Length
= min(Length
, 512);
323 /* Check if we need to verify the buffer */
324 if (PreviousMode
!= KernelMode
)
326 /* Capture user-mode buffers */
329 ProbeForRead(String
, Length
, 1);
330 CapturedString
= alloca(512);
331 RtlMoveMemory(CapturedString
, String
, Length
);
332 String
= CapturedString
;
334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
336 _SEH2_YIELD(return STATUS_ACCESS_VIOLATION
);
341 /* Setup the output string */
342 OutputString
.Buffer
= String
;
343 OutputString
.Length
= Length
;
346 //KdLogDbgPrint(&OutputString);
348 /* Check for a debugger */
349 if (KdDebuggerNotPresent
)
353 return STATUS_DEVICE_NOT_CONNECTED
;
356 /* Enter the debugger */
357 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
359 /* Print the string */
360 if (KdpPrintString(&OutputString
))
362 /* User pressed CTRL-C, breakpoint on return */
363 ReturnStatus
= STATUS_BREAKPOINT
;
367 /* String was printed */
368 ReturnStatus
= STATUS_SUCCESS
;
371 /* Exit the debugger and return */
372 KdExitDebugger(Enable
);
379 KdpDprintf(IN PCHAR Format
,
387 /* Format the string */
388 va_start(ap
, Format
);
389 Length
= (USHORT
)_vsnprintf(Buffer
,
395 String
.Buffer
= Buffer
;
396 String
.Length
= Length
+ 1;
398 /* Send it to the debugger directly */
399 KdpPrintString(&String
);