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 *****************************************************************/
26 DBGKD_DEBUG_IO DebugIo
;
30 KdpMoveMemory(KdpMessageBuffer
,
34 /* Make sure we don't exceed the KD Packet size */
35 Length
= Output
->Length
;
36 if ((sizeof(DBGKD_DEBUG_IO
) + Length
) > PACKET_MAX_SIZE
)
38 /* Normalize length */
39 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_DEBUG_IO
);
42 /* Build the packet header */
43 DebugIo
.ApiNumber
= DbgKdPrintStringApi
;
44 DebugIo
.ProcessorLevel
= (USHORT
)KeProcessorLevel
;
45 DebugIo
.Processor
= KeGetCurrentPrcb()->Number
;
46 DebugIo
.u
.PrintString
.LengthOfString
= Length
;
47 Header
.Length
= sizeof(DBGKD_DEBUG_IO
);
48 Header
.Buffer
= (PCHAR
)&DebugIo
;
52 Data
.Buffer
= KdpMessageBuffer
;
55 KdSendPacket(PACKET_TYPE_KD_DEBUG_IO
, &Header
, &Data
, &KdpContext
);
57 /* Check if the user pressed CTRL+C */
58 return KdpPollBreakInWithPortLock();
64 _In_ PSTRING PromptString
,
65 _In_ PSTRING ResponseString
)
68 DBGKD_DEBUG_IO DebugIo
;
72 /* Copy the string to the message buffer */
73 KdpMoveMemory(KdpMessageBuffer
,
75 PromptString
->Length
);
77 /* Make sure we don't exceed the KD Packet size */
78 Length
= PromptString
->Length
;
79 if ((sizeof(DBGKD_DEBUG_IO
) + Length
) > PACKET_MAX_SIZE
)
81 /* Normalize length */
82 Length
= PACKET_MAX_SIZE
- sizeof(DBGKD_DEBUG_IO
);
85 /* Build the packet header */
86 DebugIo
.ApiNumber
= DbgKdGetStringApi
;
87 DebugIo
.ProcessorLevel
= (USHORT
)KeProcessorLevel
;
88 DebugIo
.Processor
= KeGetCurrentPrcb()->Number
;
89 DebugIo
.u
.GetString
.LengthOfPromptString
= Length
;
90 DebugIo
.u
.GetString
.LengthOfStringRead
= ResponseString
->MaximumLength
;
91 Header
.Length
= sizeof(DBGKD_DEBUG_IO
);
92 Header
.Buffer
= (PCHAR
)&DebugIo
;
96 Data
.Buffer
= KdpMessageBuffer
;
99 KdSendPacket(PACKET_TYPE_KD_DEBUG_IO
, &Header
, &Data
, &KdpContext
);
101 /* Set the maximum lengths for the receive */
102 Header
.MaximumLength
= sizeof(DBGKD_DEBUG_IO
);
103 Data
.MaximumLength
= sizeof(KdpMessageBuffer
);
105 /* Enter receive loop */
109 Status
= KdReceivePacket(PACKET_TYPE_KD_DEBUG_IO
,
115 /* Return TRUE if we need to resend */
116 if (Status
== KdPacketNeedsResend
) return TRUE
;
118 /* Loop until we succeed */
119 } while (Status
!= KdPacketReceived
);
121 /* Don't copy back a larger response than there is room for */
123 ResponseString
->MaximumLength
);
125 /* Copy back the string and return the length */
126 KdpMoveMemory(ResponseString
->Buffer
,
129 ResponseString
->Length
= (USHORT
)Length
;
131 /* Success; we don't need to resend */
137 KdpCommandString(IN PSTRING NameString
,
138 IN PSTRING CommandString
,
139 IN KPROCESSOR_MODE PreviousMode
,
140 IN PCONTEXT ContextRecord
,
141 IN PKTRAP_FRAME TrapFrame
,
142 IN PKEXCEPTION_FRAME ExceptionFrame
)
145 PKPRCB Prcb
= KeGetCurrentPrcb();
147 /* Check if we need to do anything */
148 if ((PreviousMode
!= KernelMode
) || (KdDebuggerNotPresent
)) return;
150 /* Enter the debugger */
151 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
153 /* Save the CPU Control State and save the context */
154 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
155 KdpMoveMemory(&Prcb
->ProcessorState
.ContextFrame
,
159 /* Send the command string to the debugger */
160 KdpReportCommandStringStateChange(NameString
,
162 &Prcb
->ProcessorState
.ContextFrame
);
164 /* Restore the processor state */
165 KdpMoveMemory(ContextRecord
,
166 &Prcb
->ProcessorState
.ContextFrame
,
168 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
170 /* Exit the debugger and return */
171 KdExitDebugger(Enable
);
176 KdpSymbol(IN PSTRING DllPath
,
177 IN PKD_SYMBOLS_INFO SymbolInfo
,
179 IN KPROCESSOR_MODE PreviousMode
,
180 IN PCONTEXT ContextRecord
,
181 IN PKTRAP_FRAME TrapFrame
,
182 IN PKEXCEPTION_FRAME ExceptionFrame
)
185 PKPRCB Prcb
= KeGetCurrentPrcb();
187 /* Check if we need to do anything */
188 if ((PreviousMode
!= KernelMode
) || (KdDebuggerNotPresent
)) return;
190 /* Enter the debugger */
191 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
193 /* Save the CPU Control State and save the context */
194 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
195 KdpMoveMemory(&Prcb
->ProcessorState
.ContextFrame
,
199 /* Report the new state */
200 KdpReportLoadSymbolsStateChange(DllPath
,
203 &Prcb
->ProcessorState
.ContextFrame
);
205 /* Restore the processor state */
206 KdpMoveMemory(ContextRecord
,
207 &Prcb
->ProcessorState
.ContextFrame
,
209 KiRestoreProcessorControlState(&Prcb
->ProcessorState
);
211 /* Exit the debugger and return */
212 KdExitDebugger(Enable
);
221 _In_ PSTRING Output
);
227 _In_ PSTRING PromptString
,
228 _In_ PSTRING ResponseString
);
235 _In_reads_bytes_(PromptLength
) PCHAR PromptString
,
236 _In_ USHORT PromptLength
,
237 _Out_writes_bytes_(MaximumResponseLength
) PCHAR ResponseString
,
238 _In_ USHORT MaximumResponseLength
,
239 _In_ KPROCESSOR_MODE PreviousMode
,
240 _In_ PKTRAP_FRAME TrapFrame
,
241 _In_ PKEXCEPTION_FRAME ExceptionFrame
)
243 STRING PromptBuffer
, ResponseBuffer
;
244 BOOLEAN Enable
, Resend
;
245 PCHAR SafeResponseString
;
246 CHAR CapturedPrompt
[512];
247 CHAR SafeResponseBuffer
[512];
249 /* Normalize the lengths */
250 PromptLength
= min(PromptLength
,
251 sizeof(CapturedPrompt
));
252 MaximumResponseLength
= min(MaximumResponseLength
,
253 sizeof(SafeResponseBuffer
));
255 /* Check if we need to verify the string */
256 if (PreviousMode
!= KernelMode
)
258 /* Handle user-mode buffers safely */
261 /* Probe and capture the prompt */
262 ProbeForRead(PromptString
, PromptLength
, 1);
263 KdpMoveMemory(CapturedPrompt
, PromptString
, PromptLength
);
264 PromptString
= CapturedPrompt
;
266 /* Probe and make room for the response */
267 ProbeForWrite(ResponseString
, MaximumResponseLength
, 1);
268 SafeResponseString
= SafeResponseBuffer
;
270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
272 /* Bad string pointer, bail out */
273 _SEH2_YIELD(return 0);
279 SafeResponseString
= ResponseString
;
282 /* Setup the prompt and response buffers */
283 PromptBuffer
.Buffer
= PromptString
;
284 PromptBuffer
.Length
= PromptBuffer
.MaximumLength
= PromptLength
;
285 ResponseBuffer
.Buffer
= SafeResponseString
;
286 ResponseBuffer
.Length
= 0;
287 ResponseBuffer
.MaximumLength
= MaximumResponseLength
;
290 //KdLogDbgPrint(&PromptBuffer);
292 /* Enter the debugger */
293 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
295 /* Enter prompt loop */
298 /* Send the prompt and receive the response */
299 Resend
= KdpPromptString(&PromptBuffer
, &ResponseBuffer
);
301 /* Loop while we need to resend */
304 /* Exit the debugger */
305 KdExitDebugger(Enable
);
307 /* Copy back the response if required */
308 if (PreviousMode
!= KernelMode
)
312 /* Safely copy back the response to user mode */
313 KdpMoveMemory(ResponseString
,
314 ResponseBuffer
.Buffer
,
315 ResponseBuffer
.Length
);
317 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
319 /* String became invalid after we exited, fail */
320 _SEH2_YIELD(return 0);
325 /* Return the number of characters received */
326 return ResponseBuffer
.Length
;
332 _In_ ULONG ComponentId
,
334 _In_reads_bytes_(Length
) PCHAR String
,
336 _In_ KPROCESSOR_MODE PreviousMode
,
337 _In_ PKTRAP_FRAME TrapFrame
,
338 _In_ PKEXCEPTION_FRAME ExceptionFrame
,
339 _Out_ PBOOLEAN Handled
)
344 CHAR CapturedString
[512];
349 #if (NTDDI_VERSION >= NTDDI_VISTA)
350 if ((ComponentId
>= KdComponentTableSize
) && (ComponentId
< MAXULONG
))
352 /* Use the default component ID */
353 Mask
= &Kd_DEFAULT_Mask
;
354 // Level = DPFLTR_INFO_LEVEL; // Override the Level.
357 /* Convert Level to bit field if required */
358 if (Level
< 32) Level
= 1 << Level
;
359 Level
&= ~DPFLTR_MASK
;
361 /* Validate the mask */
362 if (!(Kd_WIN2000_Mask
& Level
) ||
363 ((ComponentId
< KdComponentTableSize
) &&
364 !(*KdComponentTable
[ComponentId
] & Level
)))
366 /* Mask validation failed */
368 return STATUS_SUCCESS
;
371 /* Normalize the length */
372 Length
= min(Length
, sizeof(CapturedString
));
374 /* Check if we need to verify the string */
375 if (PreviousMode
!= KernelMode
)
377 /* Capture user-mode buffers */
380 /* Probe and capture the string */
381 ProbeForRead(String
, Length
, 1);
382 KdpMoveMemory(CapturedString
, String
, Length
);
383 String
= CapturedString
;
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
387 /* Bad string pointer, bail out */
388 _SEH2_YIELD(return STATUS_ACCESS_VIOLATION
);
393 /* Setup the output string */
394 OutputString
.Buffer
= String
;
395 OutputString
.Length
= OutputString
.MaximumLength
= Length
;
398 //KdLogDbgPrint(&OutputString);
400 /* Check for a debugger */
401 if (KdDebuggerNotPresent
)
405 return STATUS_DEVICE_NOT_CONNECTED
;
408 /* Enter the debugger */
409 Enable
= KdEnterDebugger(TrapFrame
, ExceptionFrame
);
411 /* Print the string */
412 if (KdpPrintString(&OutputString
))
414 /* User pressed CTRL-C, breakpoint on return */
415 Status
= STATUS_BREAKPOINT
;
419 /* String was printed */
420 Status
= STATUS_SUCCESS
;
423 /* Exit the debugger and return */
424 KdExitDebugger(Enable
);
440 /* Format the string */
441 va_start(ap
, Format
);
442 Length
= (USHORT
)_vsnprintf(Buffer
,
449 String
.Buffer
= Buffer
;
450 String
.Length
= String
.MaximumLength
= Length
;
452 /* Send it to the debugger directly */
453 KdpPrintString(&String
);