/*++ Copyright (c) 2000 Microsoft Corporation Module Name: debug.h Abstract: Debug macros for NDISPROT Notes: --*/ /// 防止多次include #ifndef _NUIODEBUG__H #define _NUIODEBUG__H // // Message verbosity: lower values indicate higher urgency /// 低的values值,表明更高的输出,直接说就是比程序预定值低的values就会输出调试信息 /// 输出DEBUG信息时,使用下面定义的常量,越低输出的可能性越大。 /// ? #define DL_EXTRA_LOUD 20 /// ? #define DL_VERY_LOUD 10 /// ? #define DL_LOUD 8 /// 信息 #define DL_INFO 6 /// 警告 #define DL_WARN 4 /// 错误 #define DL_ERROR 2 /// 严重的错误 #define DL_FATAL 0 /// 如果是定义了DBG_SPIN_LOCK #if DBG_SPIN_LOCK typedef struct _NPROT_LOCK { /// 签名 ULONG Signature; /// 是不是已经得到锁,就是是否已经加锁 ULONG IsAcquired; /// 自己的线程,就是加锁时所在的线程 PKTHREAD OwnerThread; /// 使用这个数据结构时候,在哪个文件 ULONG TouchedByFileNumber; /// 使用这个数据结构时候,在哪行代码 ULONG TouchedInLineNumber; /// 这个是真正起作用的锁,如果是Release用,只有这个成员 NDIS_SPIN_LOCK NdisLock; } NPROT_LOCK, *PNPROT_LOCK; /// 本文件的签名,对应上面的TouchedByFileNumber /// 注意'KCOL',这个编译后就是个32位值,也就是一个Int类型的数 /// 这种技巧是否依赖于编译器,要查看C语言的说明书 #define NUIOL_SIG 'KCOL' /// 向语法扫描器说明该变量(ndisprotDbgLogLock)在别的文件(debug.c)中已经定义 /// NDIS_SPIN_LOCK定义在ndis.h中 /// typedef struct _NDIS_SPIN_LOCK /// { /// /// 在winnt.h中看到,typedef ULONG_PTR KSPIN_LOCK; /// /// 对于ULONG_PTR,大概是typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR; /// /// 具体每个平台下的不同,限于水平,不能深究。 /// /// 结论:KSPIN_LOCK -> ULONG_PTR -> 对应一个长指针 /// /// 可以想象,所谓锁就是整型指针,加锁和解锁就是对指向内容的修改,互斥就是对指向内容的判断 /// KSPIN_LOCK SpinLock; /// /// ? OldIrql的作用现在还不清楚,分析后面的代码有可能知道 /// KIRQL OldIrql; /// } NDIS_SPIN_LOCK, * PNDIS_SPIN_LOCK; extern NDIS_SPIN_LOCK ndisprotDbgLogLock; /// 以下的extern声明的例程都定义在debug.c文件中 /// 其中FileNumber和LineNumber的作用是输出Log时候,表明是哪个文件的哪行代码输出的 /// 分配锁 extern VOID ndisprotAllocateSpinLock( IN PNPROT_LOCK pLock, IN ULONG FileNumber, IN ULONG LineNumber ); /// 释放锁,注意不是解锁 extern VOID ndisprotFreeSpinLock( IN PNPROT_LOCK pLock, IN ULONG FileNumber, IN ULONG LineNumber ); /// 加锁 extern VOID ndisprotAcquireSpinLock( IN PNPROT_LOCK pLock, IN ULONG FileNumber, IN ULONG LineNumber ); /// 解锁 extern VOID ndisprotReleaseSpinLock( IN PNPROT_LOCK pLock, IN ULONG FileNumber, IN ULONG LineNumber ); /// 释放锁,这个锁是debug.c文件中使用的,因为是对结构体的成员做些操作, /// 为了保证唯一性,都需要加锁和解锁 extern VOID ndisprotFreeDbgLock( VOID ); /// 定义一个宏,检查锁定的次数 #define CHECK_LOCK_COUNT(Count) / { / if ((INT)(Count) < 0) / { / DbgPrint("Lock Count %d is < 0! File %s, Line %d/n",/ Count, __FILE__, __LINE__); / DbgBreakPoint(); / } / } #else /// 下面是没有定义DBG_SPIN_LOCK的情况 /// 定义一个空白的宏 #define CHECK_LOCK_COUNT(Count) /// 直接定义锁,从这里可以看出,保持代码在DEBUG版本和RELEASE版本不需要修改的技巧 /// 就在于保持接口一致,这里的接口包括变量的名字和例程的名字 typedef NDIS_SPIN_LOCK NPROT_LOCK; typedef PNDIS_SPIN_LOCK PNPROT_LOCK; #endif // DBG_SPIN_LOCK /// 关于DBG_SPIN_LOCK的定义就结束了 /// 下面开始关于其他DBG的定义 #if DBG /// /// 向语法扫描器说明该变量(ndisprotDebugLevel)在别的文件(debug.c)中已经定义 extern INT ndisprotDebugLevel; /// 定义DEBUGP宏 #define DEBUGP(lev, stmt) / { / /// 如果lev<=ndisprotDebugLevel,那么输出调试信息 /// ? 注意DbgPrint stmt; if ((lev) <= ndisprotDebugLevel) / { / DbgPrint("NdisProt: "); DbgPrint stmt; / } / } /// 定义DEBUGPDUMP宏 #define DEBUGPDUMP(lev, pBuf, Len) / { / if ((lev) <= ndisprotDebugLevel) / { / DbgPrintHexDump((PUCHAR)(pBuf), (ULONG)(Len)); / } / } /// 定义NPROT_ASSERT宏 #define NPROT_ASSERT(exp) / { / if (!(exp)) / { / DbgPrint("NdisProt: assert " #exp " failed in" / " file %s, line %d/n", __FILE__, __LINE__); / DbgBreakPoint(); / } / } /// 设置信号 /// 注意t##_sig,用t字符替换t##字符以后,再处理 /// 假设调用形式是:NPROT_SET_SIGNATURE(pOpenContext, oc); /// 替换以后的形式是:pOpenContext->oc_sig = oc_signature; #define NPROT_SET_SIGNATURE(s, t)/ (s)->t##_sig = t##_signature; /// 断言,检查信号 #define NPROT_STRUCT_ASSERT(s, t) / if ((s)->t##_sig != t##_signature) / { / DbgPrint("ndisprot: assertion failure" / " for type " #t " at 0x%p in file %s, line %d/n", / (PUCHAR)s, __FILE__, __LINE__); / DbgBreakPoint(); / } /// 内存的分配释放检查 // // Memory Allocation/Freeing Audit: // /// NUIOD_ALLOCATION结构体存储了分配内存块的所有信息 // // The NUIOD_ALLOCATION structure stores all info about one allocation // typedef struct _NUIOD_ALLOCATION { /// 签名 ULONG Signature; /// 后向指针 struct _NUIOD_ALLOCATION *Next; /// 前向指针 struct _NUIOD_ALLOCATION *Prev; /// 分配结构体的内存时所在的文件 ULONG FileNumber; /// 分配结构体的内存时所在的行号 ULONG LineNumber; /// 用户分配的内存的大小 ULONG Size; /// 用户分配的内存的开始位置 ULONG_PTR Location; // where the returned ptr was stored union { /// 对齐方式 ULONGLONG Alignment; /// 用户数据 UCHAR UserData; }; } NUIOD_ALLOCATION, *PNUIOD_ALLOCATION; /// 对应NUIOD_ALLOCATION中的Signature /// 注意'CSII',这个编译后就是个32位值,也就是一个Int类型的数 #define NUIOD_MEMORY_SIGNATURE (ULONG)'CSII' /// 以下的extern声明的例程都定义在debug.c文件中 /// 其中FileNumber和LineNumber的作用是输出Log时候,表明是哪个文件的哪行代码输出的 extern PVOID ndisprotAuditAllocMem ( PVOID pPointer, ULONG Size, ULONG FileNumber, ULONG LineNumber ); extern VOID ndisprotAuditFreeMem( PVOID Pointer ); extern VOID ndisprotAuditShutdown( VOID ); extern VOID DbgPrintHexDump( PUCHAR pBuffer, ULONG Length ); #else /// DBG以外 /// 下面的宏都是空白的,说明以上的例程和结构体只用于调试代码 /// 如果不慎用在非调试代码中就没有什么作用 // // No debug // #define DEBUGP(lev, stmt) #define DEBUGPDUMP(lev, pBuf, Len) #define NPROT_ASSERT(exp) #define NPROT_SET_SIGNATURE(s, t) #define NPROT_STRUCT_ASSERT(s, t) #endif // DBG #endif // _NUIODEBUG__H