- Fix critical bugs in DR_TRAP_FIXUP, TRAP_PROLOG and TRAP_EPILOG which would either...
[reactos.git] / reactos / lib / rtl / debug.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Run-Time Library
4 * FILE: ntoskrnl/rtl/dbgprint.c
5 * PURPOSE: Debug Print and Prompt routines
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Royce Mitchel III
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <rtl.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* PRIVATE FUNCTIONS ********************************************************/
18
19 NTSTATUS
20 NTAPI
21 DebugPrint(IN PANSI_STRING DebugString,
22 IN ULONG ComponentId,
23 IN ULONG Level)
24 {
25 /* Call the INT2D Service */
26 return STATUS_SUCCESS;
27 return DebugService(BREAKPOINT_PRINT,
28 DebugString->Buffer,
29 DebugString->Length,
30 UlongToPtr(ComponentId),
31 UlongToPtr(Level));
32 }
33
34 NTSTATUS
35 NTAPI
36 DebugPrompt(IN PCSTRING Output,
37 IN PSTRING Input)
38 {
39 /* Call the INT2D Service */
40 return DebugService(BREAKPOINT_PROMPT,
41 Output->Buffer,
42 Output->Length,
43 Input->Buffer,
44 UlongToPtr(Input->MaximumLength));
45 }
46
47 /* FUNCTIONS ****************************************************************/
48
49 ULONG
50 NTAPI
51 vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix,
52 IN ULONG ComponentId,
53 IN ULONG Level,
54 IN LPCSTR Format,
55 IN va_list ap,
56 IN BOOLEAN HandleBreakpoint)
57 {
58 NTSTATUS Status;
59 ANSI_STRING DebugString;
60 CHAR Buffer[512];
61 PCHAR pBuffer = Buffer;
62 ULONG pBufferSize = sizeof(Buffer);
63 ULONG Length;
64 EXCEPTION_RECORD ExceptionRecord;
65
66 /* Check if we should print it or not */
67 if (ComponentId != -1 && !NtQueryDebugFilterState(ComponentId, Level))
68 {
69 /* This message is masked */
70 return STATUS_SUCCESS;
71 }
72
73 /* For user mode, don't recursively DbgPrint */
74 if (RtlpSetInDbgPrint(TRUE)) return STATUS_SUCCESS;
75
76 /* Initialize the length to 8 */
77 DebugString.Length = 0;
78
79 /* Handle the prefix */
80 if (Prefix && *Prefix)
81 {
82 /* Get the length */
83 DebugString.Length = strlen(Prefix);
84
85 /* Normalize it */
86 if(DebugString.Length > sizeof(Buffer))
87 {
88 DebugString.Length = sizeof(Buffer);
89 }
90
91 /* Copy it */
92 strncpy(Buffer, Prefix, DebugString.Length);
93
94 /* Set the pointer and update the size */
95 pBuffer = &Buffer[DebugString.Length];
96 pBufferSize -= DebugString.Length;
97 }
98
99 /* Setup the ANSI String */
100 DebugString.Buffer = Buffer;
101 DebugString.MaximumLength = sizeof(Buffer);
102 Length = _vsnprintf(pBuffer, pBufferSize, Format, ap);
103
104 /* Check if we went past the buffer */
105 if (Length == -1)
106 {
107 /* Terminate it if we went over-board */
108 Buffer[sizeof(Buffer) - 1] = '\n';
109
110 /* Put maximum */
111 Length = sizeof(Buffer);
112 }
113
114 /* Update length */
115 DebugString.Length += (USHORT)Length;
116
117 /* First, let the debugger know as well */
118 if (RtlpCheckForActiveDebugger(FALSE))
119 {
120 /* Fill out an exception record */
121 ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C;
122 ExceptionRecord.ExceptionRecord = NULL;
123 ExceptionRecord.NumberParameters = 2;
124 ExceptionRecord.ExceptionFlags = 0;
125 ExceptionRecord.ExceptionInformation[0] = DebugString.Length + 1;
126 ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR)DebugString.Buffer;
127
128 /* Raise the exception */
129 RtlRaiseException(&ExceptionRecord);
130
131 /* This code only runs in user-mode, so setting the flag is safe */
132 NtCurrentTeb()->InDbgPrint = FALSE;
133 return STATUS_SUCCESS;
134 }
135
136 /* Call the Debug Print routine */
137 Status = DebugPrint(&DebugString, ComponentId, Level);
138
139 /* Check if this was with Control-C */
140 if (HandleBreakpoint)
141 {
142 /* Check if we got a breakpoint */
143 if (Status == STATUS_BREAKPOINT)
144 {
145 /* Breakpoint */
146 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
147 Status = STATUS_SUCCESS;
148 }
149 }
150
151 /* In user-mode, remove the InDbgPrint Flag */
152 RtlpSetInDbgPrint(FALSE);
153
154 /* Return */
155 return Status;
156 }
157
158 /*
159 * @implemented
160 */
161 ULONG
162 NTAPI
163 vDbgPrintExWithPrefix(IN LPCSTR Prefix,
164 IN ULONG ComponentId,
165 IN ULONG Level,
166 IN LPCSTR Format,
167 IN va_list ap)
168 {
169 /* Call the internal routine that also handles ControlC */
170 return vDbgPrintExWithPrefixInternal(Prefix,
171 ComponentId,
172 Level,
173 Format,
174 ap,
175 TRUE);
176 }
177
178 /*
179 * @implemented
180 */
181 ULONG
182 NTAPI
183 vDbgPrintEx(IN ULONG ComponentId,
184 IN ULONG Level,
185 IN LPCSTR Format,
186 IN va_list ap)
187 {
188 /* Call the internal routine that also handles ControlC */
189 return vDbgPrintExWithPrefixInternal(NULL,
190 ComponentId,
191 Level,
192 Format,
193 ap,
194 TRUE);
195 }
196
197 /*
198 * @implemented
199 */
200 ULONG
201 __cdecl
202 DbgPrint(PCCH Format,
203 ...)
204 {
205 va_list ap;
206
207 /* Call the internal routine that also handles ControlC */
208 va_start(ap, Format);
209 return vDbgPrintExWithPrefixInternal(NULL,
210 -1,
211 DPFLTR_ERROR_LEVEL,
212 Format,
213 ap,
214 TRUE);
215 va_end(ap);
216 }
217
218 /*
219 * @implemented
220 */
221 ULONG
222 __cdecl
223 DbgPrintEx(IN ULONG ComponentId,
224 IN ULONG Level,
225 IN PCCH Format,
226 ...)
227 {
228 va_list ap;
229
230 /* Call the internal routine that also handles ControlC */
231 va_start(ap, Format);
232 return vDbgPrintExWithPrefixInternal(NULL,
233 ComponentId,
234 Level,
235 Format,
236 ap,
237 TRUE);
238 va_end(ap);
239 }
240
241 /*
242 * @implemented
243 */
244 ULONG
245 __cdecl
246 DbgPrintReturnControlC(PCH Format,
247 ...)
248 {
249 va_list ap;
250
251 /* Call the internal routine that also handles ControlC */
252 va_start(ap, Format);
253 return vDbgPrintExWithPrefixInternal(NULL,
254 -1,
255 DPFLTR_ERROR_LEVEL,
256 Format,
257 ap,
258 FALSE);
259 }
260
261 /*
262 * @implemented
263 */
264 ULONG
265 NTAPI
266 DbgPrompt(IN PCCH Prompt,
267 OUT PCH Response,
268 IN ULONG MaximumResponseLength)
269 {
270 CSTRING Output;
271 STRING Input;
272
273 /* Setup the input string */
274 Input.MaximumLength = (USHORT)MaximumResponseLength;
275 Input.Buffer = Response;
276
277 /* Setup the output string */
278 Output.Length = strlen(Prompt);
279 Output.Buffer = Prompt;
280
281 /* Call the system service */
282 return DebugPrompt(&Output, &Input);
283 }
284
285 /*
286 * @implemented
287 */
288 NTSTATUS
289 NTAPI
290 DbgQueryDebugFilterState(IN ULONG ComponentId,
291 IN ULONG Level)
292 {
293 /* Call the Nt routine */
294 return NtQueryDebugFilterState(ComponentId, Level);
295 }
296
297 /*
298 * @implemented
299 */
300 NTSTATUS
301 NTAPI
302 DbgSetDebugFilterState(IN ULONG ComponentId,
303 IN ULONG Level,
304 IN BOOLEAN State)
305 {
306 /* Call the Nt routine */
307 return NtSetDebugFilterState(ComponentId, Level, State);
308 }
309
310 /*
311 * @implemented
312 */
313 NTSTATUS
314 NTAPI
315 DbgLoadImageSymbols(IN PANSI_STRING Name,
316 IN PVOID Base,
317 IN ULONG ProcessId)
318 {
319 PIMAGE_NT_HEADERS NtHeader;
320 KD_SYMBOLS_INFO SymbolInfo;
321
322 /* Setup the symbol data */
323 SymbolInfo.BaseOfDll = Base;
324 SymbolInfo.ProcessId = (ULONG)ProcessId;
325
326 /* Get NT Headers */
327 NtHeader = RtlImageNtHeader(Base);
328 if (NtHeader)
329 {
330 /* Get the rest of the data */
331 SymbolInfo.CheckSum = NtHeader->OptionalHeader.CheckSum;
332 SymbolInfo.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
333 }
334 else
335 {
336 /* No data available */
337 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0;
338 }
339
340 /* Load the symbols */
341 DebugService2(Name, &SymbolInfo, BREAKPOINT_LOAD_SYMBOLS);
342 return STATUS_SUCCESS;
343 }
344
345 /*
346 * @implemented
347 */
348 VOID
349 NTAPI
350 DbgUnLoadImageSymbols(IN PANSI_STRING Name,
351 IN PVOID Base,
352 IN ULONG_PTR ProcessId)
353 {
354 KD_SYMBOLS_INFO SymbolInfo;
355
356 /* Setup the symbol data */
357 SymbolInfo.BaseOfDll = Base;
358 SymbolInfo.ProcessId = (ULONG)ProcessId;
359 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0;
360
361 /* Load the symbols */
362 DebugService2(Name, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS);
363 }
364
365 /* EOF */