NDIS 6.85 协议驱动开发实战基于 WDK 10 构建 3 个核心回调函数示例在 Windows 网络驱动开发领域NDISNetwork Driver Interface Specification协议驱动扮演着承上启下的关键角色。本文将聚焦 NDIS 6.85 版本使用 WDK 10 开发环境通过实战演示如何构建一个完整的协议驱动框架重点实现 BindAdapterHandlerEx、SendNetBufferListsCompleteHandler 和 ReceiveNetBufferListsHandler 这三个核心回调函数。1. NDIS 协议驱动开发环境准备在开始编码之前我们需要配置合适的开发环境。以下是必需的开发工具和组件Visual Studio 2019建议使用 16.11 或更高版本WDK 10确保安装版本与 Windows 10 21H2 SDK 匹配Windows 10 21H2 SDK提供必要的头文件和库测试机器运行 Windows 10 21H2 或更高版本的物理机或虚拟机环境配置关键步骤# 安装 WDK 扩展的 VS 项目模板 Install-WindowsDriverKit -Version 10.0.19041.0 -Components WDKVSIX开发环境验证清单在 Visual Studio 中确认 Windows Driver 项目模板可用检查%WindowsSdkDir%\Include\10.0.19041.0\km路径下的 NDIS 头文件验证ndis.lib是否存在于 SDK 库目录注意WDK 10 与 Visual Studio 的集成度很高但需要特别注意版本兼容性。建议使用完全匹配的 WDK 和 SDK 版本以避免编译问题。2. NDIS 协议驱动基础架构NDIS 协议驱动位于网络协议栈的上层主要职责包括提供协议接口给上层应用程序处理来自下层驱动的网络数据包管理与小端口驱动的绑定关系2.1 驱动入口与注册协议驱动的入口点仍然是标准的DriverEntry函数但其主要工作是注册协议特性NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NDIS_PROTOCOL_DRIVER_CHARACTERISTICS protoChars; NDIS_HANDLE ndisProtocolHandle; // 初始化协议驱动特征结构 NdisZeroMemory(protoChars, sizeof(protoChars)); protoChars.Header.Type NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS; protoChars.Header.Size sizeof(NDIS_PROTOCOL_DRIVER_CHARACTERISTICS); protoChars.Header.Revision NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; protoChars.MajorNdisVersion NDIS_MAJOR_VERSION; protoChars.MinorNdisVersion NDIS_MINOR_VERSION; // 设置核心回调函数 protoChars.BindAdapterHandlerEx MyBindAdapterHandlerEx; protoChars.UnbindAdapterHandlerEx MyUnbindAdapterHandlerEx; protoChars.SendNetBufferListsCompleteHandler MySendNetBufferListsCompleteHandler; protoChars.ReceiveNetBufferListsHandler MyReceiveNetBufferListsHandler; // 注册协议驱动 NDIS_STATUS status NdisRegisterProtocolDriver( NULL, // DriverContext protoChars, // Characteristics ndisProtocolHandle // NdisProtocolHandle ); if (status ! NDIS_STATUS_SUCCESS) { DbgPrint(协议驱动注册失败: 0x%08X, status); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }关键数据结构说明结构成员描述必需性BindAdapterHandlerEx绑定适配器时的回调必需UnbindAdapterHandlerEx解绑适配器时的回调必需SendNetBufferListsCompleteHandler发送完成通知必需ReceiveNetBufferListsHandler接收数据包处理必需OpenAdapterCompleteHandlerEx打开适配器完成通知可选CloseAdapterCompleteHandlerEx关闭适配器完成通知可选3. 实现 BindAdapterHandlerEx 回调BindAdapterHandlerEx是协议驱动中最重要的回调之一当 NDIS 需要将协议驱动与小端口驱动绑定时调用此函数。3.1 绑定处理流程NDIS_STATUS MyBindAdapterHandlerEx( _In_ NDIS_HANDLE ProtocolDriverContext, _In_ NDIS_HANDLE BindContext, _In_ PNDIS_BIND_PARAMETERS BindParameters ) { // 1. 分配绑定上下文 PMY_PROTOCOL_BINDING binding (PMY_PROTOCOL_BINDING)ExAllocatePoolZero( NonPagedPoolNx, sizeof(MY_PROTOCOL_BINDING), MY_POOL_TAG); if (binding NULL) { return NDIS_STATUS_RESOURCES; } // 2. 初始化绑定结构 binding-ProtocolBindingContext BindContext; binding-AdapterName BindParameters-AdapterName; // 3. 设置打开参数 NDIS_OPEN_PARAMETERS openParams; NdisZeroMemory(openParams, sizeof(openParams)); openParams.Header.Type NDIS_OBJECT_TYPE_OPEN_PARAMETERS; openParams.Header.Size sizeof(NDIS_OPEN_PARAMETERS); openParams.Header.Revision NDIS_OPEN_PARAMETERS_REVISION_1; openParams.AdapterName BindParameters-AdapterName; openParams.Medium BindParameters-Medium; openParams.SelectedMediumIndex BindParameters-MediumArrayIndex; // 4. 打开适配器 NDIS_STATUS status NdisOpenAdapterEx( ProtocolDriverContext, binding, openParams, BindContext, binding-NdisBindingHandle ); if (status ! NDIS_STATUS_SUCCESS) { ExFreePoolWithTag(binding, MY_POOL_TAG); return status; } // 5. 保存绑定信息到全局列表 ExInterlockedInsertTailList( g_BindingList, binding-Link, g_BindingListLock); return NDIS_STATUS_SUCCESS; }3.2 绑定上下文管理协议驱动通常需要维护每个绑定的状态信息。以下是推荐的绑定上下文结构typedef struct _MY_PROTOCOL_BINDING { LIST_ENTRY Link; // 全局绑定列表的链接 NDIS_HANDLE NdisBindingHandle; // NDIS 绑定句柄 PNDIS_STRING AdapterName; // 适配器名称 NDIS_HANDLE ProtocolBindingContext; // 协议绑定上下文 // 统计信息 ULONG64 TotalPacketsReceived; ULONG64 TotalPacketsSent; // 其他驱动特定数据... } MY_PROTOCOL_BINDING, *PMY_PROTOCOL_BINDING;绑定过程中的常见问题与解决方案资源不足检查内存池使用情况实现适当的错误恢复机制适配器不支持验证BindParameters-Medium是否符合预期检查适配器能力并发绑定问题使用同步机制保护全局绑定列表考虑使用ExInterlocked系列函数4. 实现 SendNetBufferListsCompleteHandler 回调当协议驱动通过NdisSendNetBufferLists发送的数据包完成处理时NDIS 会调用此回调函数。4.1 发送完成处理实现VOID MySendNetBufferListsCompleteHandler( _In_ NDIS_HANDLE ProtocolBindingContext, _In_ PNET_BUFFER_LIST NetBufferList, _In_ ULONG SendCompleteFlags ) { PMY_PROTOCOL_BINDING binding (PMY_PROTOCOL_BINDING)ProtocolBindingContext; // 遍历 NET_BUFFER_LIST 链 PNET_BUFFER_LIST currentNbl NetBufferList; while (currentNbl ! NULL) { PNET_BUFFER_LIST nextNbl NET_BUFFER_LIST_NEXT_NBL(currentNbl); // 更新统计信息 InterlockedIncrement64(binding-TotalPacketsSent); // 释放发送时分配的资源 PMY_SEND_CONTEXT sendContext (PMY_SEND_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(currentNbl); if (sendContext ! NULL) { ExFreePoolWithTag(sendContext, MY_SEND_CONTEXT_TAG); } // 将 NBL 返回给我们的发送池 MyReturnSendNetBufferList(currentNbl); currentNbl nextNbl; } }4.2 NET_BUFFER_LIST 处理技巧链式处理NET_BUFFER_LIST可能是一个链式结构必须遍历整个链处理每个节点上下文管理使用NET_BUFFER_LIST_CONTEXT_DATA_START存取自定义上下文上下文通常在发送前分配并设置性能优化实现 NBL 池减少内存分配开销批量处理完成的 NBL发送完成标志解析标志含义NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL当前 IRQL DISPATCH_LEVELNDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE单源虚拟端口发送完成5. 实现 ReceiveNetBufferListsHandler 回调当底层驱动接收到网络数据包时会通过此回调将数据包传递给协议驱动。5.1 接收处理核心实现VOID MyReceiveNetBufferListsHandler( _In_ NDIS_HANDLE ProtocolBindingContext, _In_ PNET_BUFFER_LIST NetBufferLists, _In_ NDIS_PORT_NUMBER PortNumber, _In_ ULONG NumberOfNetBufferLists, _In_ ULONG ReceiveFlags ) { PMY_PROTOCOL_BINDING binding (PMY_PROTOCOL_BINDING)ProtocolBindingContext; PNET_BUFFER_LIST currentNbl NetBufferLists; PNET_BUFFER_LIST nblsToIndicate NULL; // 更新统计信息 InterlockedAdd64(binding-TotalPacketsReceived, NumberOfNetBufferLists); while (currentNbl ! NULL) { PNET_BUFFER_LIST nextNbl NET_BUFFER_LIST_NEXT_NBL(currentNbl); NET_BUFFER_LIST_NEXT_NBL(currentNbl) NULL; // 1. 检查数据包是否应该被处理 if (MyFilterPacket(currentNbl)) { // 添加到待指示列表 NET_BUFFER_LIST_NEXT_NBL(currentNbl) nblsToIndicate; nblsToIndicate currentNbl; } else { // 2. 释放不被接受的包 NdisReturnNetBufferLists(currentNbl, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } currentNbl nextNbl; } // 3. 将过滤后的包传递给上层 if (nblsToIndicate ! NULL) { MyIndicatePacketsToUpperLayer(binding, nblsToIndicate); } }5.2 数据包处理最佳实践性能关键路径尽量减少每个数据包的处理时间避免在接收路径中进行内存分配数据包检查使用NdisGetDataBuffer安全访问数据验证数据包长度和完整性接收标志处理接收标志处理建议NDIS_RECEIVE_FLAGS_RESOURCES尽快释放资源NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL避免分页操作NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE优化单类型处理数据包处理示例代码BOOLEAN MyFilterPacket(PNET_BUFFER_LIST nbl) { PNET_BUFFER nb NET_BUFFER_LIST_FIRST_NB(nbl); ULONG etherType 0; // 获取以太网类型字段 PUCHAR data (PUCHAR)NdisGetDataBuffer( nb, sizeof(ETHERNET_HEADER), NULL, 1, 0); if (data ! NULL) { PETHERNET_HEADER ethHeader (PETHERNET_HEADER)data; etherType RtlUshortByteSwap(ethHeader-EtherType); } // 只接受 IPv4 和 ARP 包 return (etherType ETHERTYPE_IPV4 || etherType ETHERTYPE_ARP); }6. 协议驱动编译与调试完成核心回调函数的实现后我们需要编译并调试驱动程序。6.1 编译配置在 Visual Studio 项目中确保以下配置正确PropertyGroup LabelConfiguration TargetVersionWindows 10/TargetVersion PlatformToolsetWindowsKernelModeDriver10.0/PlatformToolset ConfigurationTypeDriver/ConfigurationType DriverTypeNDIS/DriverType /PropertyGroup必备编译选项启用警告等级 4 (/W4)将 NDIS 版本宏设置为 6.85 (NDIS_MINIPORT_MAJOR_VERSION6,NDIS_MINIPORT_MINOR_VERSION85)禁用 C 异常 (/kernel)启用静态代码分析6.2 调试技巧使用 WinDbg 进行内核调试设置符号路径!sym noisy; .sympath srv*https://msdl.microsoft.com/download/symbols加载驱动符号.reload /f YourDriver.sys常用调试命令# 查看 NDIS 协议驱动状态 !ndiskd.protocol # 检查特定协议驱动 !ndiskd.protocol -p YourProtocolName # 查看绑定关系 !ndiskd.miniport -b日志记录策略使用DbgPrintEx进行分级日志记录实现环形缓冲区存储关键事件考虑使用 WPP 跟踪常见问题排查表问题现象可能原因解决方案绑定失败适配器不支持检查BindParameters-Medium发送卡死NBL 未正确释放验证发送完成回调接收不到数据过滤条件太严格检查接收过滤逻辑内存泄漏上下文未释放使用 PoolMon 检查标签7. 进阶开发技巧掌握了基本实现后下面介绍一些提升协议驱动质量和性能的进阶技巧。7.1 性能优化策略NBL 池化技术#define MY_NBL_POOL_SIZE 64 VOID InitializeNblPool() { NDIS_STATUS status; NET_BUFFER_LIST_POOL_PARAMETERS poolParams; NdisZeroMemory(poolParams, sizeof(poolParams)); poolParams.Header.Type NDIS_OBJECT_TYPE_DEFAULT; poolParams.Header.Size sizeof(poolParams); poolParams.Header.Revision NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; poolParams.ProtocolId NDIS_PROTOCOL_ID_TCP_IP; poolParams.fAllocateNetBuffer TRUE; poolParams.ContextSize sizeof(MY_NBL_CONTEXT); poolParams.PoolSize MY_NBL_POOL_SIZE; g_MyNblPool NdisAllocateNetBufferListPool(NULL, poolParams); }批处理发送与接收积累多个 NBL 后批量发送使用NDIS_SEND_FLAGS_DISPATCH_LEVEL优化高 IRQL 发送零拷贝接收直接处理原始 NBL 而不复制数据使用NdisRetreatNetBufferDataStart调整缓冲区7.2 稳定性增强内存安全使用ExAllocatePoolZero初始化内存实现完善的释放检查异常处理__try { // 可能引发异常的代码 ProcessPacketContents(nbl); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint(包处理异常: 0x%08X, GetExceptionCode()); NdisReturnNetBufferLists(nbl, 0); }电源管理实现ProtocolNetPnPEvent处理电源事件正确处理NetEventSetPower通知7.3 与用户模式通信协议驱动通常需要与用户态应用程序通信常见方法包括IOCTL 接口创建控制设备对象实现IRP_MJ_DEVICE_CONTROL处理共享内存使用MmAllocateContiguousMemory分配通过 IOCTL 传递内存信息事件通知内核触发事件用户态等待使用KeSetEvent和CreateEvent配对用户模式通信示例NTSTATUS HandleUserIoctl( _In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp ) { PIO_STACK_LOCATION irpStack IoGetCurrentIrpStackLocation(Irp); ULONG ioctlCode irpStack-Parameters.DeviceIoControl.IoControlCode; switch (ioctlCode) { case IOCTL_GET_STATS: { PMY_STATS stats (PMY_STATS)Irp-AssociatedIrp.SystemBuffer; // 填充统计信息 stats-TotalReceived g_GlobalStats.TotalReceived; stats-TotalSent g_GlobalStats.TotalSent; Irp-IoStatus.Information sizeof(MY_STATS); Irp-IoStatus.Status STATUS_SUCCESS; break; } // 其他 IOCTL 处理... } IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }8. 实际应用场景扩展NDIS 协议驱动在实际项目中有多种应用方式以下是几个典型场景的实现思路。8.1 网络监控与分析数据包捕获在ReceiveNetBufferListsHandler中复制感兴趣的数据包通过共享内存或 IOCTL 提供给用户态流量统计维护每个绑定的计数器按协议类型分类统计连接跟踪解析 TCP/IP 头信息维护连接状态表8.2 协议扩展实现自定义协议注册新的以太类型处理特定格式的数据包协议转换接收一种协议的数据转换为另一种协议格式发送加密隧道在发送路径加密数据在接收路径解密数据8.3 网络过滤与防火墙包过滤基于五元组源/目的 IP、端口、协议过滤实现白名单/黑名单机制内容过滤检查应用层内容关键字匹配与阻断速率限制统计单位时间流量超限时丢弃或延迟数据包过滤规则数据结构示例typedef struct _MY_FILTER_RULE { LIST_ENTRY Link; ULONG RuleId; UCHAR SrcIp[4]; UCHAR DstIp[4]; USHORT SrcPort; USHORT DstPort; UCHAR Protocol; UCHAR Action; // 0允许, 1拒绝 } MY_FILTER_RULE, *PMY_FILTER_RULE;9. 测试与验证策略完善的测试是确保驱动稳定性的关键特别是对于运行在内核模式的网络驱动。9.1 测试环境搭建硬件配置至少两台测试机器发送端和接收端可选交换机或集线器监控流量软件工具Wireshark抓包验证Netperf/PingPlotter性能测试Driver Verifier驱动验证器测试网络拓扑[发送端] ---- [测试机运行驱动] ---- [接收端] | [监控端]9.2 功能测试用例基本通信测试Ping 测试TCP/UDP 数据传输绑定/解绑测试热插拔网络适配器禁用/启用网络接口异常测试无效数据包注入资源耗尽情况测试自动化测试脚本示例# 驱动安装测试 $driverPath C:\Drivers\MyProtocolDriver.inf pnputil /add-driver $driverPath /install # 绑定状态检查 Get-NetAdapterBinding -ComponentID MyProtocolDriver # 基本网络测试 Test-NetConnection -ComputerName 192.168.1.100 -Port 809.3 性能测试指标吞吐量测试使用 iPerf 测量 TCP/UDP 吞吐量比较有/无驱动时的性能差异延迟测试Ping 延迟统计请求-响应循环测试资源使用内存占用PoolMon 监控CPU 使用率Xperf 分析性能优化检查表[ ] NBL 重用机制实现[ ] 批处理操作使用[ ] 高频路径无内存分配[ ] 锁竞争最小化[ ] 上下文切换减少10. 部署与维护考虑将协议驱动部署到生产环境需要考虑以下方面。10.1 安装包制作INF 文件要点[Version] Signature $WINDOWS NT$ Class NetService ClassGuid {4D36E974-E325-11CE-BFC1-08002BE10318} Provider %ManufacturerName% CatalogFile MyProtocolDriver.cat DriverVer 06/21/2023,1.0.0.0 [Manufacturer] %ManufacturerName% MyCompany [MyCompany] %MyProtocolDriver.ServiceDesc% MyProtocolDriver_Install, NDIS [MyProtocolDriver_Install] AddReg MyProtocolDriver_AddReg [MyProtocolDriver_AddReg] HKR, Ndi, Service, 0, MyProtocolDriver HKR, Ndi, CoServices, 0x00010000, MyProtocolDriver数字签名要求测试签名用于开发阶段发布需要 WHQL 或 EV 代码签名证书10.2 版本升级策略兼容性维护保持 NDIS 版本兼容二进制接口稳定性热升级实现ProtocolUninstallHandler支持无缝重新加载10.3 故障排查工具日志收集ETW 事件跟踪系统事件日志诊断命令# 查看已加载的 NDIS 驱动 sc query type driver group NDIS # 检查驱动依赖 driversect.exe MyProtocolDriver.sys崩溃分析WinDbg 分析内存转储!analyze -v 自动分析11. 安全最佳实践网络驱动作为系统关键组件必须遵循严格的安全准则。11.1 输入验证数据包验证检查长度字段有效性验证缓冲区边界IOCTL 安全验证输入/输出缓冲区大小检查调用者权限11.2 内存安全池内存防护使用NonPagedPoolNx启用池标记追踪缓冲区访问使用NdisGetDataBuffer安全访问避免直接指针运算11.3 认证与授权安装控制要求管理员权限验证安装包完整性运行时保护限制用户模式访问实现权限检查安全审计清单[ ] 所有输入数据验证[ ] 无未初始化内存使用[ ] 无缓冲区溢出风险[ ] 适当的权限检查[ ] 安全的内存释放12. 未来兼容性设计随着 Windows 和 NDIS 的演进驱动设计应考虑未来兼容性。12.1 NDIS 版本适配版本检测NDIS_GET_VERSION(MajorVersion, MinorVersion); if (MajorVersion 6 || (MajorVersion 6 MinorVersion 85)) { DbgPrint(不支持的 NDIS 版本); return STATUS_NOT_SUPPORTED; }功能协商使用NdisSetOptionalHandlers按版本启用不同功能12.2 新特性利用RSC (Receive Segment Coalescing)支持大包处理减少中断开销QoS 支持流量分类优先级处理节能特性空闲时降低功耗支持 NDIS 电源管理12.3 64 位与 ARM 支持指针精度使用ULONG_PTR代替ULONG避免 32/64 位假设内存对齐使用DECLSPEC_ALIGN检查跨平台对齐要求字节序处理使用RtlUshortByteSwap等函数明确网络/主机字节序转换13. 性能调优实战通过实际案例展示如何分析和优化协议驱动性能。13.1 性能分析工具Xperf/WPACPU 使用率分析上下文切换跟踪ETW 提供程序NDIS 内置事件自定义驱动事件PoolMon内存池使用监控泄漏检测13.2 常见瓶颈与解决锁竞争使用无锁数据结构缩小临界区范围内存分配预分配资源池减少分配频率缓存效应优化数据结构布局提高缓存命中率性能优化前后对比指标优化前优化后提升吞吐量800 Mbps1.2 Gbps50%CPU 使用率45%30%33%内存分配次数/秒15,00050030x13.3 零拷贝优化案例原始接收路径// 分配新缓冲区并复制数据 PVOID newBuffer ExAllocatePoolWithTag(...); NdisMoveMemory(newBuffer, packetData, dataLength);优化后// 直接使用原始 NBL ProcessPacketInPlace(nbl); NdisReturnNetBufferLists(nbl, 0);14. 调试技巧与实战深入探讨 NDIS 协议驱动特有的调试技术。14.1 崩溃分析常见崩溃场景无效指针解引用竞态条件内存破坏分析步骤# 加载转储文件 .opendump crash.dmp # 自动分析 !analyze -v # 检查 NDIS 状态 !ndiskd.protocol14.2 实时调试断点设置硬件断点ba e1 MyFunction条件断点bp /t $proc MyFunction j (poi(esp8)0) gc; 内存检查检查池损坏!poolused 2验证链表!list -t LIST_ENTRY.Flink -x dt MY_STRUCT $extret Head14.3 日志策略分级日志#define LOG_LEVEL_ERROR 1 #define LOG_LEVEL_WARNING 2 #define LOG_LEVEL_INFO 3 VOID MyLog(ULONG Level, PCSTR Format, ...) { if (Level g_CurrentLogLevel) { va_list args; va_start(args, Format); vDbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, Format, args); va_end(args); } }环形缓冲区固定大小内存区域原子更新读写指针15. 资源管理与清理协议驱动必须妥善管理资源避免泄漏和系统不稳定。15.1 资源类型与生命周期资源类型分配函数释放函数生命周期内存池ExAllocatePoolZeroExFreePool绑定期间NDIS 句柄NdisOpenAdapterExNdisCloseAdapter绑定期间NBL 池NdisAllocateNetBufferListPoolNdisFreeNetBufferListPool驱动全局锁NdisAllocateSpinLockNdisFreeSpinLock绑定或全局15.2 清理流程实现VOID MyCleanupBindings() { PLIST_ENTRY entry; while ((entry ExInterlockedRemoveHeadList( g_BindingList, g_BindingListLock)) ! NULL) { PMY_PROTOCOL_BINDING binding CONTAINING_RECORD( entry, MY_PROTOCOL_BINDING, Link); // 关闭适配器 if (binding-NdisBindingHandle ! NULL) { NdisCloseAdapter(binding-NdisBindingHandle); } // 释放绑定结构 ExFreePoolWithTag(binding, MY_POOL_TAG); } }15.3 卸载处理VOID MyUnload(_In_ PDRIVER_OBJECT DriverObject) { // 1. 注销协议驱动 if (g_NdisProtocolHandle ! NULL) { NdisDeregisterProtocolDriver(g_NdisProtocolHandle); } // 2. 清理所有绑定 MyCleanupBindings(); // 3. 释放全局资源 if (g_MyNblPool ! NULL) { NdisFreeNetBufferListPool(g_MyNblPool); } // 4. 删除设备对象等... }资源泄漏检查表[ ] 所有绑定正确关闭[ ] 所有内存池释放[ ] 无未完成的 NBL[ ] 锁和事件对象清理[ ] 设备对象和符号链接删除16. 跨版本兼容性处理确保驱动在不同 Windows 和 NDIS 版本上正常工作。16.1 版本检测与适配NDIS_GET_VERSION(majorVersion, minorVersion); if (majorVersion 6 minorVersion 85) { // NDIS 6.85 特性 protoChars.Header.Revision NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2; } else { // 早期版本兼容模式 protoChars.Header.Revision NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; }16.2 条件编译策略#if (NDIS_SUPPORT_NDIS685) // NDIS 6.85 特定代码 protoChars.ReceiveNetBufferListsHandlerEx MyReceiveNetBufferListsHandlerEx; #else // 兼容实现 protoChars.ReceiveNetBufferListsHandler MyReceiveNetBufferListsHandler; #endif16.3 运行时功能检测NDIS_STATUS status NdisQueryAdapterInstanceName( adapterName, adapterNameLength); if (status NDIS_STATUS_NOT_SUPPORTED) { // 回退到其他方法 GetAdapterNameAlternativeWay(); }17. 高级话题与过滤驱动协作协议驱动常与过滤驱动配合使用需要特别注意交互方式。17.1 绑定顺序控制INF 文件配置[MyProtocolDriver_Install.NT.Services] AddService MyProtocolDriver, 0x00000002, MyProtocolDriver_ServiceInstall [MyProtocolDriver_ServiceInstall] DisplayName %MyProtocolDriver.ServiceDesc% ServiceType 1 ; SERVICE_KERNEL_DRIVER StartType 3 ; SERVICE_DEMAND_START ErrorControl 1 ; SERVICE_ERROR_NORMAL ServiceBinary %12%\MyProtocolDriver.sys AddReg MyProtocolDriver_AddReg LoadOrderGroup NDIS绑定优先级修改注册表UpperBindings/LowerBindings使用INetCfg