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