ReactOS  0.4.14-dev-49-gfb4591c
kdprint.c
Go to the documentation of this file.
1 /*
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)
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 BOOLEAN
19 NTAPI
21 {
23  DBGKD_DEBUG_IO DebugIo;
24  USHORT Length;
25 
26  /* Copy the string */
28  Output->Buffer,
29  Output->Length);
30 
31  /* Make sure we don't exceed the KD Packet size */
32  Length = Output->Length;
33  if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
34  {
35  /* Normalize length */
37  }
38 
39  /* Build the packet header */
42  DebugIo.Processor = KeGetCurrentPrcb()->Number;
44  Header.Length = sizeof(DBGKD_DEBUG_IO);
45  Header.Buffer = (PCHAR)&DebugIo;
46 
47  /* Build the data */
48  Data.Length = Length;
49  Data.Buffer = KdpMessageBuffer;
50 
51  /* Send the packet */
53 
54  /* Check if the user pressed CTRL+C */
56 }
57 
58 BOOLEAN
59 NTAPI
60 KdpPromptString(IN PSTRING PromptString,
61  IN PSTRING ResponseString)
62 {
64  DBGKD_DEBUG_IO DebugIo;
65  ULONG Length;
67 
68  /* Copy the string to the message buffer */
70  PromptString->Buffer,
71  PromptString->Length);
72 
73  /* Make sure we don't exceed the KD Packet size */
74  Length = PromptString->Length;
75  if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
76  {
77  /* Normalize length */
79  }
80 
81  /* Build the packet header */
82  DebugIo.ApiNumber = DbgKdGetStringApi;
84  DebugIo.Processor = KeGetCurrentPrcb()->Number;
86  DebugIo.u.GetString.LengthOfStringRead = ResponseString->MaximumLength;
87  Header.Length = sizeof(DBGKD_DEBUG_IO);
88  Header.Buffer = (PCHAR)&DebugIo;
89 
90  /* Build the data */
91  Data.Length = Length;
92  Data.Buffer = KdpMessageBuffer;
93 
94  /* Send the packet */
96 
97  /* Set the maximum lengths for the receive */
98  Header.MaximumLength = sizeof(DBGKD_DEBUG_IO);
99  Data.MaximumLength = sizeof(KdpMessageBuffer);
100 
101  /* Enter receive loop */
102  do
103  {
104  /* Get our reply */
106  &Header,
107  &Data,
108  &Length,
109  &KdpContext);
110 
111  /* Return TRUE if we need to resend */
112  if (Status == KdPacketNeedsResend) return TRUE;
113 
114  /* Loop until we succeed */
115  } while (Status != KdPacketReceived);
116 
117  /* Don't copy back a larger response than there is room for */
118  Length = min(Length,
119  ResponseString->MaximumLength);
120 
121  /* Copy back the string and return the length */
122  KdpMoveMemory(ResponseString->Buffer,
124  Length);
125  ResponseString->Length = (USHORT)Length;
126 
127  /* Success; we don't need to resend */
128  return FALSE;
129 }
130 
131 VOID
132 NTAPI
134  IN PSTRING CommandString,
137  IN PKTRAP_FRAME TrapFrame,
138  IN PKEXCEPTION_FRAME ExceptionFrame)
139 {
140  BOOLEAN Enable;
141  PKPRCB Prcb = KeGetCurrentPrcb();
142 
143  /* Check if we need to do anything */
144  if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;
145 
146  /* Enter the debugger */
147  Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
148 
149  /* Save the CPU Control State and save the context */
153  sizeof(CONTEXT));
154 
155  /* Send the command string to the debugger */
157  CommandString,
159 
160  /* Restore the processor state */
163  sizeof(CONTEXT));
165 
166  /* Exit the debugger and return */
168 }
169 
170 VOID
171 NTAPI
173  IN PKD_SYMBOLS_INFO SymbolInfo,
174  IN BOOLEAN Unload,
177  IN PKTRAP_FRAME TrapFrame,
178  IN PKEXCEPTION_FRAME ExceptionFrame)
179 {
180  BOOLEAN Enable;
181  PKPRCB Prcb = KeGetCurrentPrcb();
182 
183  /* Check if we need to do anything */
184  if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;
185 
186  /* Enter the debugger */
187  Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
188 
189  /* Save the CPU Control State and save the context */
193  sizeof(CONTEXT));
194 
195  /* Report the new state */
197  SymbolInfo,
198  Unload,
200 
201  /* Restore the processor state */
204  sizeof(CONTEXT));
206 
207  /* Exit the debugger and return */
209 }
210 
211 USHORT
212 NTAPI
213 KdpPrompt(IN LPSTR PromptString,
214  IN USHORT PromptLength,
215  OUT PCHAR ResponseString,
218  IN PKTRAP_FRAME TrapFrame,
219  IN PKEXCEPTION_FRAME ExceptionFrame)
220 {
221  STRING PromptBuffer, ResponseBuffer;
222  BOOLEAN Enable, Resend;
223  CHAR CapturedPrompt[512];
224  CHAR SafeResponseBuffer[512];
225  PCHAR SafeResponseString;
226 
227  /* Normalize the lengths */
228  PromptLength = min(PromptLength,
229  sizeof(CapturedPrompt));
231  sizeof(SafeResponseBuffer));
232 
233  /* Check if we need to verify the string */
234  if (PreviousMode != KernelMode)
235  {
236  /* Handle user-mode buffers safely */
237  _SEH2_TRY
238  {
239  /* Probe the prompt */
240  ProbeForRead(PromptString,
241  PromptLength,
242  1);
243 
244  /* Capture prompt */
245  KdpMoveMemory(CapturedPrompt,
246  PromptString,
247  PromptLength);
248  PromptString = CapturedPrompt;
249 
250  /* Probe and make room for response */
251  ProbeForWrite(ResponseString,
253  1);
254  SafeResponseString = SafeResponseBuffer;
255  }
257  {
258  /* Bad string pointer, bail out */
259  _SEH2_YIELD(return 0);
260  }
261  _SEH2_END;
262  }
263  else
264  {
265  SafeResponseString = ResponseString;
266  }
267 
268  /* Setup the prompt and response buffers */
269  PromptBuffer.Buffer = PromptString;
270  PromptBuffer.Length = PromptLength;
271  ResponseBuffer.Buffer = SafeResponseString;
272  ResponseBuffer.Length = 0;
273  ResponseBuffer.MaximumLength = MaximumResponseLength;
274 
275  /* Log the print */
276  //KdLogDbgPrint(&PromptBuffer);
277 
278  /* Enter the debugger */
279  Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
280 
281  /* Enter prompt loop */
282  do
283  {
284  /* Send the prompt and receive the response */
285  Resend = KdpPromptString(&PromptBuffer, &ResponseBuffer);
286 
287  /* Loop while we need to resend */
288  } while (Resend);
289 
290  /* Exit the debugger */
292 
293  /* Copy back response if required */
294  if (PreviousMode != KernelMode)
295  {
296  _SEH2_TRY
297  {
298  /* Safely copy back response to user mode */
299  KdpMoveMemory(ResponseString,
300  ResponseBuffer.Buffer,
301  ResponseBuffer.Length);
302  }
304  {
305  /* String became invalid after we exited, fail */
306  _SEH2_YIELD(return 0);
307  }
308  _SEH2_END;
309  }
310 
311  /* Return the number of characters received */
312  return ResponseBuffer.Length;
313 }
314 
315 NTSTATUS
316 NTAPI
318  IN ULONG Level,
319  IN LPSTR String,
320  IN USHORT Length,
322  IN PKTRAP_FRAME TrapFrame,
323  IN PKEXCEPTION_FRAME ExceptionFrame,
325 {
326  NTSTATUS ReturnStatus;
327  BOOLEAN Enable;
328  STRING OutputString;
329  PVOID CapturedString;
330 
331  /* Assume failure */
332  *Handled = FALSE;
333 
334  /* Validate the mask */
335  if (Level < 32) Level = 1 << Level;
336  if (!(Kd_WIN2000_Mask & Level) ||
339  {
340  /* Mask validation failed */
341  *Handled = TRUE;
342  return STATUS_SUCCESS;
343  }
344 
345  /* Normalize the length */
346  Length = min(Length, 512);
347 
348  /* Check if we need to verify the buffer */
349  if (PreviousMode != KernelMode)
350  {
351  /* Capture user-mode buffers */
352  _SEH2_TRY
353  {
354  /* Probe the string */
356  Length,
357  1);
358 
359  /* Capture it */
360  CapturedString = alloca(Length);
361  KdpMoveMemory(CapturedString,
362  String,
363  Length);
364  String = CapturedString;
365  }
367  {
368  /* Bad pointer, fail the print */
370  }
371  _SEH2_END;
372  }
373 
374  /* Setup the output string */
375  OutputString.Buffer = String;
376  OutputString.Length = Length;
377 
378  /* Log the print */
379  //KdLogDbgPrint(&OutputString);
380 
381  /* Check for a debugger */
383  {
384  /* Fail */
385  *Handled = TRUE;
387  }
388 
389  /* Enter the debugger */
390  Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
391 
392  /* Print the string */
393  if (KdpPrintString(&OutputString))
394  {
395  /* User pressed CTRL-C, breakpoint on return */
396  ReturnStatus = STATUS_BREAKPOINT;
397  }
398  else
399  {
400  /* String was printed */
401  ReturnStatus = STATUS_SUCCESS;
402  }
403 
404  /* Exit the debugger and return */
406  *Handled = TRUE;
407  return ReturnStatus;
408 }
409 
410 VOID
411 __cdecl
413  ...)
414 {
415  STRING String;
416  CHAR Buffer[100];
417  USHORT Length;
418  va_list ap;
419 
420  /* Format the string */
421  va_start(ap, Format);
423  sizeof(Buffer),
424  Format,
425  ap);
426 
427  /* Set it up */
428  String.Buffer = Buffer;
429  String.Length = Length + 1;
430 
431  /* Send it to the debugger directly */
433  va_end(ap);
434 }
signed char * PCHAR
Definition: retypes.h:7
#define KdPacketReceived
Definition: kddll.h:5
ULONG LengthOfStringRead
Definition: windbgkd.h:393
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
BOOLEAN NTAPI KdpPrintString(IN PSTRING Output)
Definition: kdprint.c:20
#define __cdecl
Definition: accygwin.h:79
VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
Definition: csqtest.c:160
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
ULONG KdComponentTableSize
Definition: kddata.c:360
KDP_STATUS NTAPI KdReceivePacket(IN ULONG PacketType, OUT PSTRING MessageHeader, OUT PSTRING MessageData, OUT PULONG DataLength, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:80
VOID NTAPI KdpSymbol(IN PSTRING DllPath, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:172
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char UINT32 ComponentId
Definition: acpixf.h:1264
static WCHAR String[]
Definition: stringtable.c:55
VOID NTAPI KdExitDebugger(IN BOOLEAN Enable)
Definition: kdapi.c:1924
char * LPSTR
Definition: xmlstorage.h:182
#define PACKET_MAX_SIZE
Definition: windbgkd.h:18
ULONG ApiNumber
Definition: windbgkd.h:401
CHAR KdpMessageBuffer[0x1000]
Definition: kddata.c:127
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define alloca
Definition: malloc.h:361
_SEH2_TRY
Definition: create.c:4250
#define DbgKdGetStringApi
Definition: windbgkd.h:123
#define KdPacketNeedsResend
Definition: kddll.h:7
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define va_end(ap)
Definition: acmsvcex.h:90
Definition: Header.h:8
#define DbgKdPrintStringApi
Definition: windbgkd.h:122
ULONG LengthOfPromptString
Definition: windbgkd.h:392
CONTEXT ContextFrame
Definition: ketypes.h:531
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
VOID NTAPI KiRestoreProcessorControlState(IN PKPROCESSOR_STATE ProcessorState)
struct _DBGKD_DEBUG_IO DBGKD_DEBUG_IO
char * va_list
Definition: acmsvcex.h:78
Definition: bufpool.h:45
USHORT ProcessorLevel
Definition: windbgkd.h:402
USHORT NTAPI KdpPrompt(IN LPSTR PromptString, IN USHORT PromptLength, OUT PCHAR ResponseString, IN USHORT MaximumResponseLength, IN KPROCESSOR_MODE PreviousMode, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:213
BOOLEAN NTAPI KdpPollBreakInWithPortLock(VOID)
Definition: kdlock.c:35
KD_CONTEXT KdpContext
Definition: kdmain.c:22
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define PCHAR
Definition: match.c:90
_In_ ULONG MaximumResponseLength
Definition: kdfuncs.h:11
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
NTSTATUS NTAPI KdpPrint(IN ULONG ComponentId, IN ULONG Level, IN LPSTR String, IN USHORT Length, IN KPROCESSOR_MODE PreviousMode, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, OUT PBOOLEAN Handled)
Definition: kdprint.c:317
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
_In_ BOOLEAN Handled
Definition: ketypes.h:337
ULONG Kd_WIN2000_Mask
Definition: kdmain.c:23
VOID NTAPI KdpReportLoadSymbolsStateChange(IN PSTRING PathName, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN OUT PCONTEXT Context)
Definition: kdapi.c:1581
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:579
std::wstring STRING
Definition: fontsub.cpp:33
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
Definition: ntbasedef.h:661
char * PBOOLEAN
Definition: retypes.h:11
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
BOOLEAN NTAPI KdpPromptString(IN PSTRING PromptString, IN PSTRING ResponseString)
Definition: kdprint.c:60
Definition: arc.h:85
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:372
DBGKD_PRINT_STRING PrintString
Definition: windbgkd.h:406
DBGKD_GET_STRING GetString
Definition: windbgkd.h:407
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
unsigned short USHORT
Definition: pedump.c:61
static const char const char * DllPath
Definition: image.c:34
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44
ULONG KDSTATUS
Definition: kddll.h:4
VOID __cdecl KdpDprintf(IN PCHAR Format,...)
Definition: kdprint.c:412
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define min(a, b)
Definition: monoChain.cc:55
VOID NTAPI KdpCommandString(IN PSTRING NameString, IN PSTRING CommandString, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdprint.c:133
#define _vsnprintf
Definition: xmlstorage.h:202
union _DBGKD_DEBUG_IO::@3396 u
USHORT KeProcessorLevel
Definition: krnlinit.c:20
VOID NTAPI KdpMoveMemory(IN PVOID Destination, IN PVOID Source, IN SIZE_T Length)
Definition: kdapi.c:20
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN NTAPI KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: kdapi.c:1871
PULONG KdComponentTable[104]
Definition: kddata.c:252
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
VOID NTAPI KdSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:314
BOOLEAN KdDebuggerNotPresent
Definition: kdmain.c:18
VOID NTAPI KdpReportCommandStringStateChange(IN PSTRING NameString, IN PSTRING CommandString, IN OUT PCONTEXT Context)
Definition: kdapi.c:1653
USHORT Processor
Definition: windbgkd.h:403
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char * Format
Definition: acpixf.h:1206