- Implement VirtualMemoryInformationClass of MemorySectionName for NtQueryVirtualMemory.
[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 = STATUS_SUCCESS;
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 != -1) && !(NtQueryDebugFilterState(ComponentId, Level)))
65 {
66 /* This message is masked */
67 return Status;
68 }
69
70 /* For user mode, don't recursively DbgPrint */
71 if (RtlpSetInDbgPrint(TRUE)) return Status;
72
73 /* Guard against incorrect pointers */
74 _SEH_TRY
75 {
76 /* Get the length and normalize it */
77 PrefixLength = strlen(Prefix);
78 if (PrefixLength > sizeof(Buffer)) PrefixLength = sizeof(Buffer);
79
80 /* Copy it */
81 strncpy(Buffer, Prefix, PrefixLength);
82
83 /* Do the printf */
84 Length = _vsnprintf(Buffer + PrefixLength,
85 sizeof(Buffer) - PrefixLength,
86 Format,
87 ap);
88 }
89 _SEH_HANDLE
90 {
91 /* Fail */
92 Length = PrefixLength = 0;
93 Status = _SEH_GetExceptionCode();
94 }
95 _SEH_END;
96 if (!NT_SUCCESS(Status)) return Status;
97
98 /* Check if we went past the buffer */
99 if (Length == -1)
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 va_list ap;
206
207 /* Call the internal routine that also handles ControlC */
208 va_start(ap, Format);
209 return vDbgPrintExWithPrefixInternal("",
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("",
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("",
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_PTR 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 */