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 *****************************************************************/
14 #include <ndk/kdfuncs.h>
19 /* PRIVATE FUNCTIONS ********************************************************/
23 DebugPrint(IN PSTRING DebugString
,
27 /* Call the Debug Service */
28 return DebugService(BREAKPOINT_PRINT
,
30 UlongToPtr(DebugString
->Length
),
31 UlongToPtr(ComponentId
),
37 DebugPrompt(IN PSTRING Output
,
40 /* Call the Debug Service */
41 return DebugService(BREAKPOINT_PROMPT
,
43 UlongToPtr(Output
->Length
),
45 UlongToPtr(Input
->MaximumLength
));
48 /* FUNCTIONS ****************************************************************/
52 vDbgPrintExWithPrefixInternal(IN PCCH Prefix
,
57 IN BOOLEAN HandleBreakpoint
)
62 SIZE_T Length
, PrefixLength
;
63 EXCEPTION_RECORD ExceptionRecord
;
65 /* Check if we should print it or not */
66 if ((ComponentId
!= MAXULONG
) &&
67 (NtQueryDebugFilterState(ComponentId
, Level
)) != (NTSTATUS
)TRUE
)
69 /* This message is masked */
70 return STATUS_SUCCESS
;
73 /* For user mode, don't recursively DbgPrint */
74 if (RtlpSetInDbgPrint()) return STATUS_SUCCESS
;
76 /* Guard against incorrect pointers */
79 /* Get the length and normalize it */
80 PrefixLength
= strlen(Prefix
);
81 if (PrefixLength
> sizeof(Buffer
)) PrefixLength
= sizeof(Buffer
);
84 strncpy(Buffer
, Prefix
, PrefixLength
);
87 Length
= _vsnprintf(Buffer
+ PrefixLength
,
88 sizeof(Buffer
) - PrefixLength
,
92 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
94 /* In user-mode, clear the InDbgPrint Flag */
95 RtlpClearInDbgPrint();
97 _SEH2_YIELD(return _SEH2_GetExceptionCode());
101 /* Check if we went past the buffer */
102 if (Length
== MAXULONG
)
104 /* Terminate it if we went over-board */
105 Buffer
[sizeof(Buffer
) - 1] = '\n';
108 Length
= sizeof(Buffer
);
113 Length
+= PrefixLength
;
116 /* Build the string */
117 DebugString
.Length
= (USHORT
)Length
;
118 DebugString
.Buffer
= Buffer
;
120 /* First, let the debugger know as well */
121 if (RtlpCheckForActiveDebugger())
123 /* Fill out an exception record */
124 ExceptionRecord
.ExceptionCode
= DBG_PRINTEXCEPTION_C
;
125 ExceptionRecord
.ExceptionRecord
= NULL
;
126 ExceptionRecord
.NumberParameters
= 2;
127 ExceptionRecord
.ExceptionFlags
= 0;
128 ExceptionRecord
.ExceptionInformation
[0] = DebugString
.Length
+ 1;
129 ExceptionRecord
.ExceptionInformation
[1] = (ULONG_PTR
)DebugString
.Buffer
;
131 /* Raise the exception */
132 RtlRaiseException(&ExceptionRecord
);
134 /* In user-mode, clear the InDbgPrint Flag */
135 RtlpClearInDbgPrint();
136 return STATUS_SUCCESS
;
139 /* Call the Debug Print routine */
140 Status
= DebugPrint(&DebugString
, ComponentId
, Level
);
142 /* Check if this was with Control-C */
143 if (HandleBreakpoint
)
145 /* Check if we got a breakpoint */
146 if (Status
== STATUS_BREAKPOINT
)
149 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
150 Status
= STATUS_SUCCESS
;
154 /* In user-mode, clear the InDbgPrint Flag */
155 RtlpClearInDbgPrint();
166 vDbgPrintExWithPrefix(IN PCCH Prefix
,
167 IN ULONG ComponentId
,
172 /* Call the internal routine that also handles ControlC */
173 return vDbgPrintExWithPrefixInternal(Prefix
,
186 vDbgPrintEx(IN ULONG ComponentId
,
191 /* Call the internal routine that also handles ControlC */
192 return vDbgPrintExWithPrefixInternal("",
205 DbgPrint(PCCH Format
,
211 /* Call the internal routine that also handles ControlC */
212 va_start(ap
, Format
);
213 Status
= vDbgPrintExWithPrefixInternal("",
228 DbgPrintEx(IN ULONG ComponentId
,
236 /* Call the internal routine that also handles ControlC */
237 va_start(ap
, Format
);
238 Status
= vDbgPrintExWithPrefixInternal("",
253 DbgPrintReturnControlC(PCCH Format
,
259 /* Call the internal routine that also handles ControlC */
260 va_start(ap
, Format
);
261 Status
= vDbgPrintExWithPrefixInternal("",
276 DbgPrompt(IN PCCH Prompt
,
278 IN ULONG MaximumResponseLength
)
283 /* Setup the input string */
284 Input
.MaximumLength
= (USHORT
)MaximumResponseLength
;
285 Input
.Buffer
= Response
;
287 /* Setup the output string */
288 Output
.Length
= (USHORT
)strlen(Prompt
);
289 Output
.Buffer
= (PCHAR
)Prompt
;
291 /* Call the system service */
292 return DebugPrompt(&Output
, &Input
);
300 DbgQueryDebugFilterState(IN ULONG ComponentId
,
303 /* Call the Nt routine */
304 return NtQueryDebugFilterState(ComponentId
, Level
);
312 DbgSetDebugFilterState(IN ULONG ComponentId
,
316 /* Call the Nt routine */
317 return NtSetDebugFilterState(ComponentId
, Level
, State
);
325 DbgLoadImageSymbols(IN PSTRING Name
,
327 IN ULONG_PTR ProcessId
)
329 PIMAGE_NT_HEADERS NtHeader
;
330 KD_SYMBOLS_INFO SymbolInfo
;
332 /* Setup the symbol data */
333 SymbolInfo
.BaseOfDll
= Base
;
334 SymbolInfo
.ProcessId
= ProcessId
;
337 NtHeader
= RtlImageNtHeader(Base
);
340 /* Get the rest of the data */
341 SymbolInfo
.CheckSum
= NtHeader
->OptionalHeader
.CheckSum
;
342 SymbolInfo
.SizeOfImage
= NtHeader
->OptionalHeader
.SizeOfImage
;
346 /* No data available */
347 SymbolInfo
.CheckSum
=
348 SymbolInfo
.SizeOfImage
= 0;
351 /* Load the symbols */
352 DebugService2(Name
, &SymbolInfo
, BREAKPOINT_LOAD_SYMBOLS
);
360 DbgUnLoadImageSymbols(IN PSTRING Name
,
362 IN ULONG_PTR ProcessId
)
364 KD_SYMBOLS_INFO SymbolInfo
;
366 /* Setup the symbol data */
367 SymbolInfo
.BaseOfDll
= Base
;
368 SymbolInfo
.ProcessId
= ProcessId
;
369 SymbolInfo
.CheckSum
= SymbolInfo
.SizeOfImage
= 0;
371 /* Load the symbols */
372 DebugService2(Name
, &SymbolInfo
, BREAKPOINT_UNLOAD_SYMBOLS
);
380 DbgCommandString(IN PCCH Name
,
383 STRING NameString
, CommandString
;
385 /* Setup the strings */
386 NameString
.Buffer
= (PCHAR
)Name
;
387 NameString
.Length
= (USHORT
)strlen(Name
);
388 CommandString
.Buffer
= (PCHAR
)Command
;
389 CommandString
.Length
= (USHORT
)strlen(Command
);
391 /* Send them to the debugger */
392 DebugService2(&NameString
, &CommandString
, BREAKPOINT_COMMAND_STRING
);
400 RtlPopFrame(IN PTEB_ACTIVE_FRAME Frame
)
402 /* Restore the previous frame as the active one */
403 NtCurrentTeb()->ActiveFrame
= Frame
->Previous
;
411 RtlPushFrame(IN PTEB_ACTIVE_FRAME Frame
)
413 /* Save the current frame and set the new one as active */
414 Frame
->Previous
= NtCurrentTeb()->ActiveFrame
;
415 NtCurrentTeb()->ActiveFrame
= Frame
;
422 /* Return the frame that's currently active */
423 return NtCurrentTeb()->ActiveFrame
;