xref: /reactos/sdk/include/reactos/debug.h (revision 44323e61)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS kernel
4  * FILE:            include/reactos/debug.h
5  * PURPOSE:         Useful debugging macros
6  * PROGRAMMERS:     David Welch (welch@mcmail.com)
7  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /*
11  * NOTE: Define NDEBUG before including this header
12  * to disable debugging macros.
13  */
14 
15 #pragma once
16 
17 #ifndef __RELFILE__
18 #   ifdef __REACTOS__
19 #       include <reactos/builddir.h>
20 #       define __RELFILE__ &__FILE__[sizeof(REACTOS_SOURCE_DIR)]
21 #   else
22 #       define __RELFILE__ __FILE__
23 #   endif
24 #endif
25 
26 /* Define DbgPrint/DbgPrintEx/RtlAssert unless the NDK is used */
27 #if !defined(_RTLFUNCS_H) && !defined(_NTDDK_)
28 
29 /* Make sure we have basic types (some people include us *before* SDK)... */
30 #if !defined(_NTDEF_) && !defined(_NTDEF_H) && !defined(_WINDEF_) && !defined(_WINDEF_H)
31 #error Please include SDK first.
32 #endif
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 ULONG
39 __cdecl
40 DbgPrint(
41     _In_z_ _Printf_format_string_ PCSTR Format,
42     ...
43 );
44 
45 NTSYSAPI
46 ULONG
47 __cdecl
48 DbgPrintEx(
49     _In_ ULONG ComponentId,
50     _In_ ULONG Level,
51     _In_z_ _Printf_format_string_ PCSTR Format,
52     ...
53 );
54 
55 __analysis_noreturn
56 NTSYSAPI
57 VOID
58 NTAPI
59 RtlAssert(
60     _In_ PVOID FailedAssertion,
61     _In_ PVOID FileName,
62     _In_ ULONG LineNumber,
63     _In_opt_z_ PCHAR Message
64 );
65 
66 #ifdef __cplusplus
67 } /* extern "C" */
68 #endif
69 
70 #endif /* !defined(_RTLFUNCS_H) && !defined(_NTDDK_) */
71 
72 #ifndef assert
73 #if DBG && !defined(NASSERT)
74 #define assert(x) if (!(x)) { RtlAssert((PVOID)#x, (PVOID)__RELFILE__, __LINE__, ""); }
75 #else
76 #define assert(x) ((VOID) 0)
77 #endif
78 #endif
79 
80 #ifndef ASSERT
81 #if DBG && !defined(NASSERT)
82 #define ASSERT(x) if (!(x)) { RtlAssert((PVOID)#x, (PVOID)__RELFILE__, __LINE__, ""); }
83 #else
84 #define ASSERT(x) ((VOID) 0)
85 #endif
86 #endif
87 
88 #ifndef ASSERTMSG
89 #if DBG && !defined(NASSERT)
90 #define ASSERTMSG(m, x) if (!(x)) { RtlAssert((PVOID)#x, __RELFILE__, __LINE__, m); }
91 #else
92 #define ASSERTMSG(m, x) ((VOID) 0)
93 #endif
94 #endif
95 
96 /* For internal purposes only */
97 #define __NOTICE(level, fmt, ...)   DbgPrint(#level ":  %s at %s:%d " fmt, __FUNCTION__, __RELFILE__, __LINE__, ##__VA_ARGS__)
98 
99 /* Print stuff only on Debug Builds*/
100 #if DBG
101 
102     /* These are always printed */
103     #define DPRINT1(fmt, ...) do { \
104         if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
105             DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
106     } while (0)
107 
108     /* These are printed only if NDEBUG is NOT defined */
109     #ifndef NDEBUG
110 
111         #define DPRINT(fmt, ...) do { \
112             if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
113                 DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
114         } while (0)
115 
116     #else
117 
118 #if defined(_MSC_VER)
119         #define DPRINT   __noop
120 #else
121         #define DPRINT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
122 #endif
123 
124     #endif
125 
126     #define UNIMPLEMENTED         __NOTICE(WARNING, "is UNIMPLEMENTED!\n")
127     #define UNIMPLEMENTED_ONCE    do { static int bWarnedOnce = 0; if (!bWarnedOnce) { bWarnedOnce++; UNIMPLEMENTED; } } while (0)
128 
129     #define ERR_(ch, fmt, ...)    DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_ERROR_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
130     #define WARN_(ch, fmt, ...)   DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_WARNING_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
131     #define TRACE_(ch, fmt, ...)  DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_TRACE_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
132     #define INFO_(ch, fmt, ...)   DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_INFO_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
133 
134     #define ERR__(ch, fmt, ...)    DbgPrintEx(ch, DPFLTR_ERROR_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
135     #define WARN__(ch, fmt, ...)   DbgPrintEx(ch, DPFLTR_WARNING_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
136     #define TRACE__(ch, fmt, ...)  DbgPrintEx(ch, DPFLTR_TRACE_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
137     #define INFO__(ch, fmt, ...)   DbgPrintEx(ch, DPFLTR_INFO_LEVEL, "(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__)
138 
139 #else /* not DBG */
140 
141     /* On non-debug builds, we never show these */
142     #define UNIMPLEMENTED
143     #define UNIMPLEMENTED_ONCE
144 #if defined(_MSC_VER)
145     #define DPRINT1   __noop
146     #define DPRINT    __noop
147 
148     #define ERR_(ch, ...)      __noop
149     #define WARN_(ch, ...)     __noop
150     #define TRACE_(ch, ...)    __noop
151     #define INFO_(ch, ...)     __noop
152 
153     #define ERR__(ch, ...)     __noop
154     #define WARN__(ch, ...)    __noop
155     #define TRACE__(ch, ...)   __noop
156     #define INFO__(ch, ...)    __noop
157 #else
158     #define DPRINT1(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
159     #define DPRINT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
160 
161     #define ERR_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
162     #define WARN_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
163     #define TRACE_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
164     #define INFO_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
165 
166     #define ERR__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
167     #define WARN__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
168     #define TRACE__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
169     #define INFO__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
170 #endif /* _MSC_VER */
171 
172 #endif /* not DBG */
173 
174 /******************************************************************************/
175 /*
176  * Declare a target-dependent process termination procedure.
177  */
178 #ifndef _NTDDK_             /* User-Mode */
179     #ifndef NTOS_MODE_USER  /* Should be Win32 */
180         #ifndef _WIN32
181             #error "Unsupported target."
182         #else
183             #define TerminateCurrentProcess(Status) TerminateProcess(GetCurrentProcess(), (Status))
184         #endif
185     #else   /* Native */
186         #ifndef _PSFUNCS_H
187             NTSYSCALLAPI
188             NTSTATUS
189             NTAPI
190             NtTerminateProcess(
191                 IN HANDLE ProcessHandle,
192                 IN NTSTATUS ExitStatus
193             );
194         #endif
195         #ifndef NtCurrentProcess
196             #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
197         #endif
198         #define TerminateCurrentProcess(Status) NtTerminateProcess(NtCurrentProcess(), (Status))
199     #endif
200 #else   /* Kernel-Mode */
201     #include <bugcodes.h>
202     #define TerminateCurrentProcess(Status) KeBugCheckEx(CRITICAL_SERVICE_FAILED, (Status), 0, 0, 0)
203 #endif
204 
205 
206 /* For internal purposes only */
207 #define __ERROR_DBGBREAK(...)   \
208 do {                            \
209     DbgPrint("" __VA_ARGS__);   \
210     DbgBreakPoint();            \
211 } while (0)
212 
213 /* For internal purposes only */
214 #define __ERROR_FATAL(Status, ...)      \
215 do {                                    \
216     DbgPrint("" __VA_ARGS__);           \
217     DbgBreakPoint();                    \
218     TerminateCurrentProcess(Status);    \
219 } while (0)
220 
221 /*
222  * These macros are designed to display an optional printf-like
223  * user-defined message and to break into the debugger.
224  * After that they allow to continue the program execution.
225  */
226 #define ERROR_DBGBREAK(...)         \
227 do {                                \
228     __NOTICE(ERROR, "\n");          \
229     __ERROR_DBGBREAK(__VA_ARGS__);  \
230 } while (0)
231 
232 #define UNIMPLEMENTED_DBGBREAK(...)         \
233 do {                                        \
234     __NOTICE(ERROR, "is UNIMPLEMENTED!\n"); \
235     __ERROR_DBGBREAK(__VA_ARGS__);          \
236 } while (0)
237 
238 /*
239  * These macros are designed to display an optional printf-like
240  * user-defined message and to break into the debugger.
241  * After that they halt the execution of the current thread.
242  */
243 #define ERROR_FATAL(...)                                    \
244 do {                                                        \
245     __NOTICE(UNRECOVERABLE ERROR, "\n");                    \
246     __ERROR_FATAL(STATUS_ASSERTION_FAILURE, __VA_ARGS__);   \
247 } while (0)
248 
249 #define UNIMPLEMENTED_FATAL(...)                            \
250 do {                                                        \
251     __NOTICE(UNRECOVERABLE ERROR, "is UNIMPLEMENTED!\n");   \
252     __ERROR_FATAL(STATUS_NOT_IMPLEMENTED, __VA_ARGS__);     \
253 } while (0)
254 /******************************************************************************/
255 
256 #define ASSERT_IRQL_LESS_OR_EQUAL(x) ASSERT(KeGetCurrentIrql()<=(x))
257 #define ASSERT_IRQL_EQUAL(x) ASSERT(KeGetCurrentIrql()==(x))
258 #define ASSERT_IRQL_LESS(x) ASSERT(KeGetCurrentIrql()<(x))
259 
260 #define __STRING2__(x) #x
261 #define __STRING__(x) __STRING2__(x)
262 #define __STRLINE__ __STRING__(__LINE__)
263 
264 #if !defined(_MSC_VER) && !defined(__pragma)
265 #define __pragma(x) _Pragma(#x)
266 #endif
267 
268 #define _WARN(msg) __pragma(message("WARNING! Line " __STRLINE__ ": " msg))
269 
270 /* EOF */
271