Reactos
at master 425 lines 11 kB view raw
1/* 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) 7 * Royce Mitchel III 8 */ 9 10/* INCLUDES *****************************************************************/ 11 12#include <rtl.h> 13 14#include <ndk/kdfuncs.h> 15 16#define NDEBUG 17#include <debug.h> 18 19/* PRIVATE FUNCTIONS ********************************************************/ 20 21ULONG 22NTAPI 23DebugPrint(IN PSTRING DebugString, 24 IN ULONG ComponentId, 25 IN ULONG Level) 26{ 27 /* Call the Debug Service */ 28 return DebugService(BREAKPOINT_PRINT, 29 DebugString->Buffer, 30 UlongToPtr(DebugString->Length), 31 UlongToPtr(ComponentId), 32 UlongToPtr(Level)); 33} 34 35ULONG 36NTAPI 37DebugPrompt(IN PSTRING Output, 38 IN PSTRING Input) 39{ 40 /* Call the Debug Service */ 41 return DebugService(BREAKPOINT_PROMPT, 42 Output->Buffer, 43 UlongToPtr(Output->Length), 44 Input->Buffer, 45 UlongToPtr(Input->MaximumLength)); 46} 47 48/* FUNCTIONS ****************************************************************/ 49 50ULONG 51NTAPI 52vDbgPrintExWithPrefixInternal(IN PCCH Prefix, 53 IN ULONG ComponentId, 54 IN ULONG Level, 55 IN PCCH Format, 56 IN va_list ap, 57 IN BOOLEAN HandleBreakpoint) 58{ 59 NTSTATUS Status; 60 STRING DebugString; 61 CHAR Buffer[512]; 62 SIZE_T Length, PrefixLength; 63 EXCEPTION_RECORD ExceptionRecord; 64 65 /* Check if we should print it or not */ 66 if ((ComponentId != MAXULONG) && 67 (NtQueryDebugFilterState(ComponentId, Level)) != (NTSTATUS)TRUE) 68 { 69 /* This message is masked */ 70 return STATUS_SUCCESS; 71 } 72 73 /* For user mode, don't recursively DbgPrint */ 74 if (RtlpSetInDbgPrint()) return STATUS_SUCCESS; 75 76 /* Guard against incorrect pointers */ 77 _SEH2_TRY 78 { 79 /* Get the length and normalize it */ 80 PrefixLength = strlen(Prefix); 81 if (PrefixLength > sizeof(Buffer)) PrefixLength = sizeof(Buffer); 82 83 /* Copy it */ 84 strncpy(Buffer, Prefix, PrefixLength); 85 86 /* Do the printf */ 87 Length = _vsnprintf(Buffer + PrefixLength, 88 sizeof(Buffer) - PrefixLength, 89 Format, 90 ap); 91 } 92 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 93 { 94 /* In user-mode, clear the InDbgPrint Flag */ 95 RtlpClearInDbgPrint(); 96 /* Fail */ 97 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 98 } 99 _SEH2_END; 100 101 /* Check if we went past the buffer */ 102 if (Length == MAXULONG) 103 { 104 /* Terminate it if we went over-board */ 105 Buffer[sizeof(Buffer) - 2] = '\n'; 106 Buffer[sizeof(Buffer) - 1] = '\0'; 107 108 /* Put maximum */ 109 Length = sizeof(Buffer) - 1; 110 } 111 else 112 { 113 /* Add the prefix */ 114 Length += PrefixLength; 115 } 116 117 /* Build the string */ 118 DebugString.Length = (USHORT)Length; 119 DebugString.Buffer = Buffer; 120 121 /* First, let the debugger know as well */ 122 if (RtlpCheckForActiveDebugger()) 123 { 124 /* Fill out an exception record */ 125 ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C; 126 ExceptionRecord.ExceptionRecord = NULL; 127 ExceptionRecord.NumberParameters = 2; 128 ExceptionRecord.ExceptionFlags = 0; 129 ExceptionRecord.ExceptionInformation[0] = DebugString.Length + 1; 130 ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR)DebugString.Buffer; 131 132 /* Raise the exception */ 133 RtlRaiseException(&ExceptionRecord); 134 135 /* In user-mode, clear the InDbgPrint Flag */ 136 RtlpClearInDbgPrint(); 137 return STATUS_SUCCESS; 138 } 139 140 /* Call the Debug Print routine */ 141 Status = DebugPrint(&DebugString, ComponentId, Level); 142 143 /* Check if this was with Control-C */ 144 if (HandleBreakpoint) 145 { 146 /* Check if we got a breakpoint */ 147 if (Status == STATUS_BREAKPOINT) 148 { 149 /* Breakpoint */ 150 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 151 Status = STATUS_SUCCESS; 152 } 153 } 154 155 /* In user-mode, clear the InDbgPrint Flag */ 156 RtlpClearInDbgPrint(); 157 158 /* Return */ 159 return Status; 160} 161 162/* 163 * @implemented 164 */ 165ULONG 166NTAPI 167vDbgPrintExWithPrefix(IN PCCH Prefix, 168 IN ULONG ComponentId, 169 IN ULONG Level, 170 IN PCCH Format, 171 IN va_list ap) 172{ 173 /* Call the internal routine that also handles ControlC */ 174 return vDbgPrintExWithPrefixInternal(Prefix, 175 ComponentId, 176 Level, 177 Format, 178 ap, 179 TRUE); 180} 181 182/* 183 * @implemented 184 */ 185ULONG 186NTAPI 187vDbgPrintEx(IN ULONG ComponentId, 188 IN ULONG Level, 189 IN PCCH Format, 190 IN va_list ap) 191{ 192 /* Call the internal routine that also handles ControlC */ 193 return vDbgPrintExWithPrefixInternal("", 194 ComponentId, 195 Level, 196 Format, 197 ap, 198 TRUE); 199} 200 201/* 202 * @implemented 203 */ 204ULONG 205__cdecl 206DbgPrint(PCCH Format, 207 ...) 208{ 209 ULONG Status; 210 va_list ap; 211 212 /* Call the internal routine that also handles ControlC */ 213 va_start(ap, Format); 214 Status = vDbgPrintExWithPrefixInternal("", 215 -1, 216 DPFLTR_ERROR_LEVEL, 217 Format, 218 ap, 219 TRUE); 220 va_end(ap); 221 return Status; 222} 223 224/* 225 * @implemented 226 */ 227ULONG 228__cdecl 229DbgPrintEx(IN ULONG ComponentId, 230 IN ULONG Level, 231 IN PCCH Format, 232 ...) 233{ 234 ULONG Status; 235 va_list ap; 236 237 /* Call the internal routine that also handles ControlC */ 238 va_start(ap, Format); 239 Status = vDbgPrintExWithPrefixInternal("", 240 ComponentId, 241 Level, 242 Format, 243 ap, 244 TRUE); 245 va_end(ap); 246 return Status; 247} 248 249/* 250 * @implemented 251 */ 252ULONG 253__cdecl 254DbgPrintReturnControlC(PCCH Format, 255 ...) 256{ 257 ULONG Status; 258 va_list ap; 259 260 /* Call the internal routine that also handles ControlC */ 261 va_start(ap, Format); 262 Status = vDbgPrintExWithPrefixInternal("", 263 -1, 264 DPFLTR_ERROR_LEVEL, 265 Format, 266 ap, 267 FALSE); 268 va_end(ap); 269 return Status; 270} 271 272/* 273 * @implemented 274 */ 275ULONG 276NTAPI 277DbgPrompt(IN PCCH Prompt, 278 OUT PCH Response, 279 IN ULONG MaximumResponseLength) 280{ 281 STRING Output; 282 STRING Input; 283 284 /* Setup the input string */ 285 Input.MaximumLength = (USHORT)MaximumResponseLength; 286 Input.Buffer = Response; 287 288 /* Setup the output string */ 289 Output.Length = (USHORT)strlen(Prompt); 290 Output.Buffer = (PCHAR)Prompt; 291 292 /* Call the system service */ 293 return DebugPrompt(&Output, &Input); 294} 295 296/* 297 * @implemented 298 */ 299NTSTATUS 300NTAPI 301DbgQueryDebugFilterState(IN ULONG ComponentId, 302 IN ULONG Level) 303{ 304 /* Call the Nt routine */ 305 return NtQueryDebugFilterState(ComponentId, Level); 306} 307 308/* 309 * @implemented 310 */ 311NTSTATUS 312NTAPI 313DbgSetDebugFilterState(IN ULONG ComponentId, 314 IN ULONG Level, 315 IN BOOLEAN State) 316{ 317 /* Call the Nt routine */ 318 return NtSetDebugFilterState(ComponentId, Level, State); 319} 320 321/* 322 * @implemented 323 */ 324VOID 325NTAPI 326DbgLoadImageSymbols(IN PSTRING Name, 327 IN PVOID Base, 328 IN ULONG_PTR ProcessId) 329{ 330 PIMAGE_NT_HEADERS NtHeader; 331 KD_SYMBOLS_INFO SymbolInfo; 332 333 /* Setup the symbol data */ 334 SymbolInfo.BaseOfDll = Base; 335 SymbolInfo.ProcessId = ProcessId; 336 337 /* Get NT Headers */ 338 NtHeader = RtlImageNtHeader(Base); 339 if (NtHeader) 340 { 341 /* Get the rest of the data */ 342 SymbolInfo.CheckSum = NtHeader->OptionalHeader.CheckSum; 343 SymbolInfo.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; 344 } 345 else 346 { 347 /* No data available */ 348 SymbolInfo.CheckSum = 349 SymbolInfo.SizeOfImage = 0; 350 } 351 352 /* Load the symbols */ 353 DebugService2(Name, &SymbolInfo, BREAKPOINT_LOAD_SYMBOLS); 354} 355 356/* 357 * @implemented 358 */ 359VOID 360NTAPI 361DbgUnLoadImageSymbols(IN PSTRING Name, 362 IN PVOID Base, 363 IN ULONG_PTR ProcessId) 364{ 365 KD_SYMBOLS_INFO SymbolInfo; 366 367 /* Setup the symbol data */ 368 SymbolInfo.BaseOfDll = Base; 369 SymbolInfo.ProcessId = ProcessId; 370 SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0; 371 372 /* Load the symbols */ 373 DebugService2(Name, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS); 374} 375 376/* 377 * @implemented 378 */ 379VOID 380NTAPI 381DbgCommandString(IN PCCH Name, 382 IN PCCH Command) 383{ 384 STRING NameString, CommandString; 385 386 /* Setup the strings */ 387 NameString.Buffer = (PCHAR)Name; 388 NameString.Length = (USHORT)strlen(Name); 389 CommandString.Buffer = (PCHAR)Command; 390 CommandString.Length = (USHORT)strlen(Command); 391 392 /* Send them to the debugger */ 393 DebugService2(&NameString, &CommandString, BREAKPOINT_COMMAND_STRING); 394} 395 396/* 397* @implemented 398*/ 399VOID 400NTAPI 401RtlPopFrame(IN PTEB_ACTIVE_FRAME Frame) 402{ 403 /* Restore the previous frame as the active one */ 404 NtCurrentTeb()->ActiveFrame = Frame->Previous; 405} 406 407/* 408* @implemented 409*/ 410VOID 411NTAPI 412RtlPushFrame(IN PTEB_ACTIVE_FRAME Frame) 413{ 414 /* Save the current frame and set the new one as active */ 415 Frame->Previous = NtCurrentTeb()->ActiveFrame; 416 NtCurrentTeb()->ActiveFrame = Frame; 417} 418 419PTEB_ACTIVE_FRAME 420NTAPI 421RtlGetFrame(VOID) 422{ 423 /* Return the frame that's currently active */ 424 return NtCurrentTeb()->ActiveFrame; 425}