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)
10 /* INCLUDES *****************************************************************/
17 /* PRIVATE FUNCTIONS ********************************************************/
21 DebugPrint(IN PSTRING DebugString
,
25 /* Call the Debug Service */
26 return DebugService(BREAKPOINT_PRINT
,
28 UlongToPtr(DebugString
->Length
),
29 UlongToPtr(ComponentId
),
35 DebugPrompt(IN PSTRING Output
,
38 /* Call the Debug Service */
39 return DebugService(BREAKPOINT_PROMPT
,
41 UlongToPtr(Output
->Length
),
43 UlongToPtr(Input
->MaximumLength
));
46 /* FUNCTIONS ****************************************************************/
50 vDbgPrintExWithPrefixInternal(IN PCCH Prefix
,
55 IN BOOLEAN HandleBreakpoint
)
60 ULONG Length
, PrefixLength
;
61 EXCEPTION_RECORD ExceptionRecord
;
63 /* Check if we should print it or not */
64 if ((ComponentId
!= MAXULONG
) &&
65 (NtQueryDebugFilterState(ComponentId
, Level
)) != TRUE
)
67 /* This message is masked */
68 return STATUS_SUCCESS
;
71 /* For user mode, don't recursively DbgPrint */
72 if (RtlpSetInDbgPrint()) return STATUS_SUCCESS
;
74 /* Guard against incorrect pointers */
77 /* Get the length and normalize it */
78 PrefixLength
= strlen(Prefix
);
79 if (PrefixLength
> sizeof(Buffer
)) PrefixLength
= sizeof(Buffer
);
82 strncpy(Buffer
, Prefix
, PrefixLength
);
85 Length
= _vsnprintf(Buffer
+ PrefixLength
,
86 sizeof(Buffer
) - PrefixLength
,
90 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
93 _SEH2_YIELD(return _SEH2_GetExceptionCode());
97 /* Check if we went past the buffer */
98 if (Length
== MAXULONG
)
100 /* Terminate it if we went over-board */
101 Buffer
[sizeof(Buffer
) - 1] = '\n';
104 Length
= sizeof(Buffer
);
109 Length
+= PrefixLength
;
112 /* Build the string */
113 DebugString
.Length
= Length
;
114 DebugString
.Buffer
= Buffer
;
116 /* First, let the debugger know as well */
117 if (RtlpCheckForActiveDebugger())
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
;
127 /* Raise the exception */
128 RtlRaiseException(&ExceptionRecord
);
130 /* This code only runs in user-mode, so setting the flag is safe */
131 NtCurrentTeb()->InDbgPrint
= FALSE
;
132 return STATUS_SUCCESS
;
135 /* Call the Debug Print routine */
136 Status
= DebugPrint(&DebugString
, ComponentId
, Level
);
138 /* Check if this was with Control-C */
139 if (HandleBreakpoint
)
141 /* Check if we got a breakpoint */
142 if (Status
== STATUS_BREAKPOINT
)
145 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
146 Status
= STATUS_SUCCESS
;
150 /* In user-mode, clear the InDbgPrint Flag */
151 RtlpClearInDbgPrint();
162 vDbgPrintExWithPrefix(IN PCCH Prefix
,
163 IN ULONG ComponentId
,
168 /* Call the internal routine that also handles ControlC */
169 return vDbgPrintExWithPrefixInternal(Prefix
,
182 vDbgPrintEx(IN ULONG ComponentId
,
187 /* Call the internal routine that also handles ControlC */
188 return vDbgPrintExWithPrefixInternal("",
201 DbgPrint(PCCH Format
,
207 /* Call the internal routine that also handles ControlC */
208 va_start(ap
, Format
);
209 Status
= vDbgPrintExWithPrefixInternal("",
224 DbgPrintEx(IN ULONG ComponentId
,
232 /* Call the internal routine that also handles ControlC */
233 va_start(ap
, Format
);
234 Status
= vDbgPrintExWithPrefixInternal("",
249 DbgPrintReturnControlC(PCCH Format
,
255 /* Call the internal routine that also handles ControlC */
256 va_start(ap
, Format
);
257 Status
= vDbgPrintExWithPrefixInternal("",
272 DbgPrompt(IN PCCH Prompt
,
274 IN ULONG MaximumResponseLength
)
279 /* Setup the input string */
280 Input
.MaximumLength
= (USHORT
)MaximumResponseLength
;
281 Input
.Buffer
= Response
;
283 /* Setup the output string */
284 Output
.Length
= strlen(Prompt
);
285 Output
.Buffer
= (PCHAR
)Prompt
;
287 /* Call the system service */
288 return DebugPrompt(&Output
, &Input
);
296 DbgQueryDebugFilterState(IN ULONG ComponentId
,
299 /* Call the Nt routine */
300 return NtQueryDebugFilterState(ComponentId
, Level
);
308 DbgSetDebugFilterState(IN ULONG ComponentId
,
312 /* Call the Nt routine */
313 return NtSetDebugFilterState(ComponentId
, Level
, State
);
321 DbgLoadImageSymbols(IN PSTRING Name
,
323 IN ULONG_PTR ProcessId
)
325 PIMAGE_NT_HEADERS NtHeader
;
326 KD_SYMBOLS_INFO SymbolInfo
;
328 /* Setup the symbol data */
329 SymbolInfo
.BaseOfDll
= Base
;
330 SymbolInfo
.ProcessId
= ProcessId
;
333 NtHeader
= RtlImageNtHeader(Base
);
336 /* Get the rest of the data */
337 SymbolInfo
.CheckSum
= NtHeader
->OptionalHeader
.CheckSum
;
338 SymbolInfo
.SizeOfImage
= NtHeader
->OptionalHeader
.SizeOfImage
;
342 /* No data available */
343 SymbolInfo
.CheckSum
=
344 SymbolInfo
.SizeOfImage
= 0;
347 /* Load the symbols */
348 DebugService2(Name
, &SymbolInfo
, BREAKPOINT_LOAD_SYMBOLS
);
356 DbgUnLoadImageSymbols(IN PSTRING Name
,
358 IN ULONG_PTR ProcessId
)
360 KD_SYMBOLS_INFO SymbolInfo
;
362 /* Setup the symbol data */
363 SymbolInfo
.BaseOfDll
= Base
;
364 SymbolInfo
.ProcessId
= ProcessId
;
365 SymbolInfo
.CheckSum
= SymbolInfo
.SizeOfImage
= 0;
367 /* Load the symbols */
368 DebugService2(Name
, &SymbolInfo
, BREAKPOINT_UNLOAD_SYMBOLS
);
376 DbgCommandString(IN PCCH Name
,
379 STRING NameString
, CommandString
;
381 /* Setup the strings */
382 NameString
.Buffer
= (PCHAR
)Name
;
383 NameString
.Length
= strlen(Name
);
384 CommandString
.Buffer
= (PCHAR
)Command
;
385 CommandString
.Length
= strlen(Command
);
387 /* Send them to the debugger */
388 DebugService2(&NameString
, &CommandString
, BREAKPOINT_COMMAND_STRING
);