[KD64]
[reactos.git] / reactos / ntoskrnl / kd64 / kdprint.c
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 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 BOOLEAN
18 NTAPI
19 KdpPrintString(IN PSTRING Output)
20 {
21 STRING Data, Header;
22 DBGKD_DEBUG_IO DebugIo;
23 USHORT Length = Output->Length;
24
25 /* Copy the string */
26 RtlMoveMemory(KdpMessageBuffer, Output->Buffer, Length);
27
28 /* Make sure we don't exceed the KD Packet size */
29 if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
30 {
31 /* Normalize length */
32 Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO);
33 }
34
35 /* Build the packet header */
36 DebugIo.ApiNumber = DbgKdPrintStringApi;
37 DebugIo.ProcessorLevel = KeProcessorLevel;
38 DebugIo.Processor = KeGetCurrentPrcb()->Number;
39 DebugIo.u.PrintString.LengthOfString = Length;
40 Header.Length = sizeof(DBGKD_DEBUG_IO);
41 Header.Buffer = (PCHAR)&DebugIo;
42
43 /* Build the data */
44 Data.Length = Length;
45 Data.Buffer = KdpMessageBuffer;
46
47 /* Send the packet */
48 KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, &Header, &Data, &KdpContext);
49
50 /* Check if the user pressed CTRL+C */
51 return KdpPollBreakInWithPortLock();
52 }
53
54 VOID
55 NTAPI
56 KdpCommandString(IN ULONG Length,
57 IN LPSTR String,
58 IN KPROCESSOR_MODE PreviousMode,
59 IN PCONTEXT ContextRecord,
60 IN PKTRAP_FRAME TrapFrame,
61 IN PKEXCEPTION_FRAME ExceptionFrame)
62 {
63 /* FIXME */
64 KdpDprintf("KdpCommandString called\n");
65 while (TRUE);
66 }
67
68 VOID
69 NTAPI
70 KdpSymbol(IN PSTRING DllPath,
71 IN PKD_SYMBOLS_INFO DllBase,
72 IN BOOLEAN Unload,
73 IN KPROCESSOR_MODE PreviousMode,
74 IN PCONTEXT ContextRecord,
75 IN PKTRAP_FRAME TrapFrame,
76 IN PKEXCEPTION_FRAME ExceptionFrame)
77 {
78 BOOLEAN Entered;
79 PKPRCB Prcb = KeGetCurrentPrcb();
80 ULONG Status;
81
82 /* Check if we need to do anything */
83 if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return;
84
85 /* Enter the debugger */
86 Entered = KdEnterDebugger(TrapFrame, ExceptionFrame);
87
88 /* Save the CPU Control State and save the context */
89 KiSaveProcessorControlState(&Prcb->ProcessorState);
90 RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
91 ContextRecord,
92 sizeof(CONTEXT));
93
94 /* Report the new state */
95 Status = KdpReportLoadSymbolsStateChange(DllPath,
96 DllBase,
97 Unload,
98 &Prcb->ProcessorState.
99 ContextFrame);
100
101 /* Now restore the processor state, manually again. */
102 RtlCopyMemory(ContextRecord,
103 &Prcb->ProcessorState.ContextFrame,
104 sizeof(CONTEXT));
105 KiRestoreProcessorControlState(&Prcb->ProcessorState);
106
107 /* Exit the debugger and clear the CTRL-C state */
108 KdExitDebugger(Entered);
109 }
110
111 BOOLEAN
112 NTAPI
113 KdpPrompt(IN LPSTR InString,
114 IN USHORT InStringLength,
115 OUT LPSTR OutString,
116 IN USHORT OutStringLength,
117 IN KPROCESSOR_MODE PreviousMode,
118 IN PKTRAP_FRAME TrapFrame,
119 IN PKEXCEPTION_FRAME ExceptionFrame)
120 {
121 /* FIXME */
122 KdpDprintf("KdpPrompt called\n");
123 while (TRUE);
124 return FALSE;
125 }
126
127 NTSTATUS
128 NTAPI
129 KdpPrint(IN ULONG ComponentId,
130 IN ULONG ComponentMask,
131 IN LPSTR String,
132 IN USHORT Length,
133 IN KPROCESSOR_MODE PreviousMode,
134 IN PKTRAP_FRAME TrapFrame,
135 IN PKEXCEPTION_FRAME ExceptionFrame,
136 OUT PBOOLEAN Status)
137 {
138 NTSTATUS ReturnStatus;
139 BOOLEAN Entered;
140 ANSI_STRING AnsiString;
141
142 /* Assume failure */
143 *Status = FALSE;
144
145 /* Validate the mask */
146 if (ComponentMask < 0x20) ComponentMask = 1 << ComponentMask;
147 if (!(Kd_WIN2000_Mask & ComponentMask) ||
148 ((ComponentId < KdComponentTableSize) &&
149 !(*KdComponentTable[ComponentId] & ComponentMask)))
150 {
151 /* Mask validation failed */
152 *Status = TRUE;
153 return FALSE;
154 }
155
156 /* Normalize the length */
157 Length = min(Length, 512);
158
159 /* Check if we need to verify the buffer */
160 if (PreviousMode != KernelMode)
161 {
162 /* FIXME: Support user-mode */
163 }
164
165 /* Setup the ANSI string */
166 AnsiString.Buffer = String;
167 AnsiString.Length = Length;
168
169 /* Log the print */
170 //KdLogDbgPrint(&AnsiString);
171
172 /* Check for a debugger */
173 if (KdDebuggerNotPresent)
174 {
175 /* Fail */
176 *Status = TRUE;
177 return STATUS_DEVICE_NOT_CONNECTED;
178 }
179
180 /* Enter the debugger */
181 Entered = KdEnterDebugger(TrapFrame, ExceptionFrame);
182
183 /* Print the string */
184 if (KdpPrintString(&AnsiString))
185 {
186 /* User pressed CTRL-C, breakpoint on return */
187 ReturnStatus = STATUS_BREAKPOINT;
188 }
189 else
190 {
191 /* String was printed */
192 ReturnStatus = STATUS_SUCCESS;
193 }
194
195 /* Exit the debugger and return */
196 KdExitDebugger(Entered);
197 *Status = TRUE;
198 return ReturnStatus;
199 }
200
201 VOID
202 __cdecl
203 KdpDprintf(IN PCHAR Format,
204 ...)
205 {
206 STRING String;
207 CHAR Buffer[100];
208 USHORT Length;
209 va_list ap;
210
211 /* Format the string */
212 va_start(ap, Format);
213 Length = (USHORT)_vsnprintf(Buffer,
214 sizeof(Buffer),
215 Format,
216 ap);
217
218 /* Set it up */
219 String.Buffer = Buffer;
220 String.Length = Length + 1;
221
222 /* Send it to the debugger directly */
223 KdpPrintString(&String);
224 va_end(ap);
225 }