7c42ebca8f4f4adc09708743c13d6823a8fb1261
[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: lib/rtl/debug.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 DebugService(BREAKPOINT_PRINT,
27 DebugString->Buffer,
28 DebugString->Length,
29 UlongToPtr(ComponentId),
30 UlongToPtr(Level));
31 }
32
33 NTSTATUS
34 NTAPI
35 DebugPrompt(IN PCSTRING Output,
36 IN PSTRING Input)
37 {
38 /* Call the INT2D Service */
39 return DebugService(BREAKPOINT_PROMPT,
40 Output->Buffer,
41 Output->Length,
42 Input->Buffer,
43 UlongToPtr(Input->MaximumLength));
44 }
45
46 /* FUNCTIONS ****************************************************************/
47
48 ULONG
49 NTAPI
50 vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix,
51 IN ULONG ComponentId,
52 IN ULONG Level,
53 IN LPCSTR Format,
54 IN va_list ap,
55 IN BOOLEAN HandleBreakpoint)
56 {
57 NTSTATUS Status;
58 ANSI_STRING DebugString;
59 CHAR Buffer[512];
60 ULONG Length, PrefixLength;
61 EXCEPTION_RECORD ExceptionRecord;
62
63 /* Check if we should print it or not */
64 if ((ComponentId != MAXULONG) &&
65 !(NtQueryDebugFilterState(ComponentId, Level)))
66 {
67 /* This message is masked */
68 return STATUS_SUCCESS;
69 }
70
71 /* For user mode, don't recursively DbgPrint */
72 if (RtlpSetInDbgPrint(TRUE)) return STATUS_SUCCESS;
73
74 /* Guard against incorrect pointers */
75 _SEH2_TRY
76 {
77 /* Get the length and normalize it */
78 PrefixLength = strlen(Prefix);
79 if (PrefixLength > sizeof(Buffer)) PrefixLength = sizeof(Buffer);
80
81 /* Copy it */
82 strncpy(Buffer, Prefix, PrefixLength);
83
84 /* Do the printf */
85 Length = _vsnprintf(Buffer + PrefixLength,
86 sizeof(Buffer) - PrefixLength,
87 Format,
88 ap);
89 }
90 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
91 {
92 /* Fail */
93 Length = PrefixLength = 0;
94 _SEH2_YIELD(return _SEH2_GetExceptionCode());
95 }
96 _SEH2_END;
97
98 /* Check if we went past the buffer */
99 if (Length == MAXULONG)
100 {
101 /* Terminate it if we went over-board */
102 Buffer[sizeof(Buffer) - 1] = '\n';
103
104 /* Put maximum */
105 Length = sizeof(Buffer);
106 }
107 else
108 {
109 /* Add the prefix */
110 Length += PrefixLength;
111 }
112
113 /* Build the string */
114 DebugString.Length = Length;
115 DebugString.Buffer = Buffer;
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("",
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 ULONG n;
206 va_list ap;
207
208 /* Call the internal routine that also handles ControlC */
209 va_start(ap, Format);
210 n = vDbgPrintExWithPrefixInternal("",
211 -1,
212 DPFLTR_ERROR_LEVEL,
213 Format,
214 ap,
215 TRUE);
216 va_end(ap);
217 return n;
218 }
219
220 /*
221 * @implemented
222 */
223 ULONG
224 __cdecl
225 DbgPrintEx(IN ULONG ComponentId,
226 IN ULONG Level,
227 IN PCCH Format,
228 ...)
229 {
230 ULONG n;
231 va_list ap;
232
233 /* Call the internal routine that also handles ControlC */
234 va_start(ap, Format);
235 n = vDbgPrintExWithPrefixInternal("",
236 ComponentId,
237 Level,
238 Format,
239 ap,
240 TRUE);
241 va_end(ap);
242 return n;
243 }
244
245 /*
246 * @implemented
247 */
248 ULONG
249 __cdecl
250 DbgPrintReturnControlC(PCH Format,
251 ...)
252 {
253 ULONG n;
254 va_list ap;
255
256 /* Call the internal routine that also handles ControlC */
257 va_start(ap, Format);
258 n = vDbgPrintExWithPrefixInternal("",
259 -1,
260 DPFLTR_ERROR_LEVEL,
261 Format,
262 ap,
263 FALSE);
264 va_end(ap);
265 return n;
266 }
267
268 /*
269 * @implemented
270 */
271 ULONG
272 NTAPI
273 DbgPrompt(IN PCCH Prompt,
274 OUT PCH Response,
275 IN ULONG MaximumResponseLength)
276 {
277 CSTRING Output;
278 STRING Input;
279
280 /* Setup the input string */
281 Input.MaximumLength = (USHORT)MaximumResponseLength;
282 Input.Buffer = Response;
283
284 /* Setup the output string */
285 Output.Length = strlen(Prompt);
286 Output.Buffer = Prompt;
287
288 /* Call the system service */
289 return DebugPrompt(&Output, &Input);
290 }
291
292 /*
293 * @implemented
294 */
295 NTSTATUS
296 NTAPI
297 DbgQueryDebugFilterState(IN ULONG ComponentId,
298 IN ULONG Level)
299 {
300 /* Call the Nt routine */
301 return NtQueryDebugFilterState(ComponentId, Level);
302 }
303
304 /*
305 * @implemented
306 */
307 NTSTATUS
308 NTAPI
309 DbgSetDebugFilterState(IN ULONG ComponentId,
310 IN ULONG Level,
311 IN BOOLEAN State)
312 {
313 /* Call the Nt routine */
314 return NtSetDebugFilterState(ComponentId, Level, State);
315 }
316
317 /*
318 * @implemented
319 */
320 VOID
321 NTAPI
322 DbgLoadImageSymbols(IN PANSI_STRING Name,
323 IN PVOID Base,
324 IN ULONG_PTR ProcessId)
325 {
326 PIMAGE_NT_HEADERS NtHeader;
327 KD_SYMBOLS_INFO SymbolInfo;
328
329 /* Setup the symbol data */
330 SymbolInfo.BaseOfDll = Base;
331 SymbolInfo.ProcessId = (ULONG)ProcessId;
332
333 /* Get NT Headers */
334 NtHeader = RtlImageNtHeader(Base);
335 if (NtHeader)
336 {
337 /* Get the rest of the data */
338 SymbolInfo.CheckSum = NtHeader->OptionalHeader.CheckSum;
339 SymbolInfo.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
340 }
341 else
342 {
343 /* No data available */
344 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0;
345 }
346
347 /* Load the symbols */
348 DebugService2(Name, &SymbolInfo, BREAKPOINT_LOAD_SYMBOLS);
349 }
350
351 /*
352 * @implemented
353 */
354 VOID
355 NTAPI
356 DbgUnLoadImageSymbols(IN PANSI_STRING Name,
357 IN PVOID Base,
358 IN ULONG_PTR ProcessId)
359 {
360 KD_SYMBOLS_INFO SymbolInfo;
361
362 /* Setup the symbol data */
363 SymbolInfo.BaseOfDll = Base;
364 SymbolInfo.ProcessId = (ULONG)ProcessId;
365 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0;
366
367 /* Load the symbols */
368 DebugService2(Name, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS);
369 }