* PROJECT: ReactOS kernel
* FILE: include/internal/debug.h
* PURPOSE: Useful debugging macros
- * PROGRAMMER: David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- * 28/05/98: Created
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/*
- * NOTE: Define NDEBUG before including this header to disable debugging
- * macros
+ * NOTE: Define NDEBUG before including this header
+ * to disable debugging macros.
*/
#ifndef __INTERNAL_DEBUG
#define __INTERNAL_DEBUG
-/* Define DbgPrint/DbgPrintEx/RtlAssert unless the NDK is used */
+/* Define DbgPrint/DbgPrintEx/RtlAssert/RtlRaiseStatus unless the NDK is used */
#if !defined(_RTLFUNCS_H) && !defined(_NTDDK_)
-/* Make sure we have basic types (some people include us *before* SDK... */
+/* Make sure we have basic types (some people include us *before* SDK)... */
#if !defined(_NTDEF_) && !defined(_NTDEF_H) && !defined(_WINDEF_) && !defined(_WINDEF_H)
#error Please include SDK first.
#endif
ULONG
__cdecl
DbgPrint(
- IN PCCH Format,
- IN ...
+ _In_z_ _Printf_format_string_ PCSTR Format,
+ ...
);
NTSYSAPI
ULONG
__cdecl
DbgPrintEx(
- IN ULONG ComponentId,
- IN ULONG Level,
- IN PCCH Format,
- IN ...
+ _In_ ULONG ComponentId,
+ _In_ ULONG Level,
+ _In_z_ _Printf_format_string_ PCCH Format,
+ ...
);
+__analysis_noreturn
NTSYSAPI
VOID
NTAPI
PCHAR Message
);
+/*
+ * This is the definition of NTSTATUS, but renamed
+ * in order not to conflict with other ones.
+ */
+typedef _Return_type_success_(return >= 0) LONG DEBUG_NTSTATUS;
+
+__analysis_noreturn
+NTSYSAPI
+VOID
+NTAPI
+RtlRaiseStatus(
+ _In_ DEBUG_NTSTATUS Status
+);
+
#endif /* !defined(_RTLFUNCS_H) && !defined(_NTDDK_) */
+
+/* Fix usage of RtlRaiseStatus */
+#if !defined(_RTLFUNCS_H) && defined(_NTDDK_)
+ #define RaiseStatus ExRaiseStatus
+#else
+ #define RaiseStatus RtlRaiseStatus
+#endif /* !defined(_RTLFUNCS_H) && defined(_NTDDK_) */
+
+
#ifndef assert
#ifndef NASSERT
-#define assert(x) if (!(x)) {RtlAssert("#x",__FILE__,__LINE__, ""); }
+#define assert(x) if (!(x)) { RtlAssert((PVOID)#x, (PVOID)__FILE__, __LINE__, ""); }
#else
#define assert(x)
#endif
#ifndef ASSERT
#ifndef NASSERT
-#define ASSERT(x) if (!(x)) {RtlAssert("#x",__FILE__,__LINE__, ""); }
+#define ASSERT(x) if (!(x)) { RtlAssert((PVOID)#x, (PVOID)__FILE__, __LINE__, ""); }
#else
#define ASSERT(x)
#endif
#ifndef ASSERTMSG
#ifndef NASSERT
-#define ASSERTMSG(x,m) if (!(x)) {RtlAssert("#x",__FILE__,__LINE__, m); }
+#define ASSERTMSG(x,m) if (!(x)) { RtlAssert((PVOID)#x, __FILE__, __LINE__, m); }
#else
#define ASSERTMSG(x)
#endif
#endif
+/* For internal purposes only */
+#define __NOTICE(level, fmt, ...) DbgPrint(#level ": %s at %s:%d " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
+
/* Print stuff only on Debug Builds*/
#define DPFLTR_DEFAULT_ID -1
#if DBG
#endif
- #define UNIMPLEMENTED DbgPrint("WARNING: %s at %s:%d is UNIMPLEMENTED!\n",__FUNCTION__,__FILE__,__LINE__);
+ #define UNIMPLEMENTED __NOTICE(WARNING, "is UNIMPLEMENTED!\n");
#define ERR_(ch, fmt, ...) DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_ERROR_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define WARN_(ch, fmt, ...) DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_WARNING_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define TRACE_(ch, fmt, ...) DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_TRACE_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define INFO_(ch, fmt, ...) DbgPrintEx(DPFLTR_##ch##_ID, DPFLTR_INFO_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
-
+
#define ERR__(ch, fmt, ...) DbgPrintEx(ch, DPFLTR_ERROR_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define WARN__(ch, fmt, ...) DbgPrintEx(ch, DPFLTR_WARNING_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define TRACE__(ch, fmt, ...) DbgPrintEx(ch, DPFLTR_TRACE_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define INFO__(ch, fmt, ...) DbgPrintEx(ch, DPFLTR_INFO_LEVEL, "(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
+
#else /* not DBG */
/* On non-debug builds, we never show these */
#define WARN_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
#define TRACE_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
#define INFO_(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
-
+
#define ERR__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
#define WARN__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
#define TRACE__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
#define INFO__(ch, ...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+
#endif /* not DBG */
+/******************************************************************************/
+/* For internal purposes only */
+#define __ERROR_DBGBREAK(...) \
+do { \
+ DbgPrint("" __VA_ARGS__); \
+ DbgBreakPoint(); \
+} while (0)
+
+/* For internal purposes only */
+#define __ERROR_FATAL(Status, ...) \
+do { \
+ DbgPrint("" __VA_ARGS__); \
+ RaiseStatus((Status)); \
+} while (0)
+
+/*
+ * These macros are designed to display an optional printf-like
+ * user-defined message and to break into the debugger.
+ * After that they allow to continue the program execution.
+ */
+#define ERROR_DBGBREAK(...) \
+do { \
+ __NOTICE(ERROR, "\n"); \
+ __ERROR_DBGBREAK(__VA_ARGS__); \
+} while (0)
+
+#define UNIMPLEMENTED_DBGBREAK(...) \
+do { \
+ __NOTICE(ERROR, "is UNIMPLEMENTED!\n"); \
+ __ERROR_DBGBREAK(__VA_ARGS__); \
+} while (0)
+
+/*
+ * These macros are designed to display an optional printf-like
+ * user-defined message and to break into the debugger.
+ * After that they halt the execution of the current thread.
+ */
+#define ERROR_FATAL(...) \
+do { \
+ __NOTICE(UNRECOVERABLE ERROR, "\n"); \
+ __ERROR_FATAL(STATUS_ASSERTION_FAILURE, __VA_ARGS__); \
+} while (0)
+
+#define UNIMPLEMENTED_FATAL(...) \
+do { \
+ __NOTICE(UNRECOVERABLE ERROR, "is UNIMPLEMENTED!\n"); \
+ __ERROR_FATAL(STATUS_NOT_IMPLEMENTED, __VA_ARGS__); \
+} while (0)
+/******************************************************************************/
+
#define ASSERT_IRQL_LESS_OR_EQUAL(x) ASSERT(KeGetCurrentIrql()<=(x))
#define ASSERT_IRQL_EQUAL(x) ASSERT(KeGetCurrentIrql()==(x))
#define ASSERT_IRQL_LESS(x) ASSERT(KeGetCurrentIrql()<(x))