- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[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 #if 0
20 NTSTATUS
21 NTAPI
22 DebugPrint(IN PANSI_STRING DebugString,
23 IN ULONG ComponentId,
24 IN ULONG Level)
25 {
26 /* Call the INT2D Service */
27 return DebugService(BREAKPOINT_PRINT,
28 DebugString->Buffer,
29 DebugString->Length,
30 UlongToPtr(ComponentId),
31 UlongToPtr(Level));
32 }
33 #else
34 NTSTATUS
35 NTAPI
36 DebugPrint(IN PANSI_STRING DebugString,
37 IN ULONG ComponentId,
38 IN ULONG Level);
39 #endif
40
41 NTSTATUS
42 NTAPI
43 DebugPrompt(IN PCSTRING Output,
44 IN PSTRING Input)
45 {
46 /* Call the INT2D Service */
47 return DebugService(BREAKPOINT_PROMPT,
48 Output->Buffer,
49 Output->Length,
50 Input->Buffer,
51 UlongToPtr(Input->MaximumLength));
52 }
53
54 /* FUNCTIONS ****************************************************************/
55
56 ULONG
57 NTAPI
58 vDbgPrintExWithPrefixInternal(IN LPCSTR Prefix,
59 IN ULONG ComponentId,
60 IN ULONG Level,
61 IN LPCSTR Format,
62 IN va_list ap,
63 IN BOOLEAN HandleBreakpoint)
64 {
65 NTSTATUS Status;
66 ANSI_STRING DebugString;
67 CHAR Buffer[512];
68 PCHAR pBuffer = Buffer;
69 ULONG pBufferSize = sizeof(Buffer);
70 ULONG Length;
71 EXCEPTION_RECORD ExceptionRecord;
72
73 /* Check if we should print it or not */
74 if (ComponentId != -1 && !NtQueryDebugFilterState(ComponentId, Level))
75 {
76 /* This message is masked */
77 return STATUS_SUCCESS;
78 }
79
80 /* For user mode, don't recursively DbgPrint */
81 if (RtlpSetInDbgPrint(TRUE)) return STATUS_SUCCESS;
82
83 /* Initialize the length to 8 */
84 DebugString.Length = 0;
85
86 /* Handle the prefix */
87 if (Prefix && *Prefix)
88 {
89 /* Get the length */
90 DebugString.Length = strlen(Prefix);
91
92 /* Normalize it */
93 if(DebugString.Length > sizeof(Buffer))
94 {
95 DebugString.Length = sizeof(Buffer);
96 }
97
98 /* Copy it */
99 strncpy(Buffer, Prefix, DebugString.Length);
100
101 /* Set the pointer and update the size */
102 pBuffer = &Buffer[DebugString.Length];
103 pBufferSize -= DebugString.Length;
104 }
105
106 /* Setup the ANSI String */
107 DebugString.Buffer = Buffer;
108 DebugString.MaximumLength = sizeof(Buffer);
109 Length = _vsnprintf(pBuffer, pBufferSize, Format, ap);
110
111 /* Check if we went past the buffer */
112 if (Length == -1)
113 {
114 /* Terminate it if we went over-board */
115 Buffer[sizeof(Buffer) - 1] = '\n';
116
117 /* Put maximum */
118 Length = sizeof(Buffer);
119 }
120
121 /* Update length */
122 DebugString.Length += Length;
123
124 /* First, let the debugger know as well */
125 if (RtlpCheckForActiveDebugger(FALSE))
126 {
127 /* Fill out an exception record */
128 ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C;
129 ExceptionRecord.ExceptionRecord = NULL;
130 ExceptionRecord.NumberParameters = 2;
131 ExceptionRecord.ExceptionFlags = 0;
132 ExceptionRecord.ExceptionInformation[0] = DebugString.Length + 1;
133 ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR)DebugString.Buffer;
134
135 /* Raise the exception */
136 RtlRaiseException(&ExceptionRecord);
137
138 /* This code only runs in user-mode, so setting the flag is safe */
139 NtCurrentTeb()->InDbgPrint = FALSE;
140 return STATUS_SUCCESS;
141 }
142
143 /* Call the Debug Print routine */
144 Status = DebugPrint(&DebugString, ComponentId, Level);
145
146 /* Check if this was with Control-C */
147 if (HandleBreakpoint)
148 {
149 /* Check if we got a breakpoint */
150 if (Status == STATUS_BREAKPOINT)
151 {
152 /* Breakpoint */
153 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
154 Status = STATUS_SUCCESS;
155 }
156 }
157
158 /* In user-mode, remove the InDbgPrint Flag */
159 RtlpSetInDbgPrint(FALSE);
160
161 /* Return */
162 return Status;
163 }
164
165 /*
166 * @implemented
167 */
168 ULONG
169 NTAPI
170 vDbgPrintExWithPrefix(IN LPCSTR Prefix,
171 IN ULONG ComponentId,
172 IN ULONG Level,
173 IN LPCSTR Format,
174 IN va_list ap)
175 {
176 /* Call the internal routine that also handles ControlC */
177 return vDbgPrintExWithPrefixInternal(Prefix,
178 ComponentId,
179 Level,
180 Format,
181 ap,
182 TRUE);
183 }
184
185 /*
186 * @implemented
187 */
188 ULONG
189 NTAPI
190 vDbgPrintEx(IN ULONG ComponentId,
191 IN ULONG Level,
192 IN LPCSTR Format,
193 IN va_list ap)
194 {
195 /* Call the internal routine that also handles ControlC */
196 return vDbgPrintExWithPrefixInternal(NULL,
197 ComponentId,
198 Level,
199 Format,
200 ap,
201 TRUE);
202 }
203
204 /*
205 * @implemented
206 */
207 ULONG
208 __cdecl
209 DbgPrint(PCCH Format,
210 ...)
211 {
212 va_list ap;
213
214 /* Call the internal routine that also handles ControlC */
215 va_start(ap, Format);
216 return vDbgPrintExWithPrefixInternal(NULL,
217 -1,
218 DPFLTR_ERROR_LEVEL,
219 Format,
220 ap,
221 TRUE);
222 va_end(ap);
223 }
224
225 /*
226 * @implemented
227 */
228 ULONG
229 __cdecl
230 DbgPrintEx(IN ULONG ComponentId,
231 IN ULONG Level,
232 IN PCCH Format,
233 ...)
234 {
235 va_list ap;
236
237 /* Call the internal routine that also handles ControlC */
238 va_start(ap, Format);
239 return vDbgPrintExWithPrefixInternal(NULL,
240 ComponentId,
241 Level,
242 Format,
243 ap,
244 TRUE);
245 va_end(ap);
246 }
247
248 /*
249 * @implemented
250 */
251 ULONG
252 __cdecl
253 DbgPrintReturnControlC(PCH Format,
254 ...)
255 {
256 va_list ap;
257
258 /* Call the internal routine that also handles ControlC */
259 va_start(ap, Format);
260 return vDbgPrintExWithPrefixInternal(NULL,
261 -1,
262 DPFLTR_ERROR_LEVEL,
263 Format,
264 ap,
265 FALSE);
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 = 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 BOOLEAN
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 NTSTATUS
321 NTAPI
322 DbgLoadImageSymbols(IN PANSI_STRING Name,
323 IN PVOID Base,
324 IN ULONG 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 = NULL; //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 return STATUS_SUCCESS;
350 }
351
352 /*
353 * @implemented
354 */
355 VOID
356 NTAPI
357 DbgUnLoadImageSymbols(IN PANSI_STRING Name,
358 IN PVOID Base,
359 IN ULONG_PTR ProcessId)
360 {
361 KD_SYMBOLS_INFO SymbolInfo;
362
363 /* Setup the symbol data */
364 SymbolInfo.BaseOfDll = Base;
365 SymbolInfo.ProcessId = (ULONG)ProcessId;
366 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0;
367
368 /* Load the symbols */
369 DebugService2(Name, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS);
370 }
371
372 /* EOF */