Windows XP系统下 NDIS中间层驱动开发

NDIS中间层驱动的开发在Win7系统上和Windows XP系统上有差别。

 我把NDIS中间层的讨论分成2块。 windows 7系统和Windows XP系统。

(一)在 Windows XP系统上进行开发
  平时很多朋友包括我在内,我们都在XP系统上使用NDIS5.1的框架来进行程序开发。我们都使用
Microsoft WDK提供的 NDIS 的 Passthru例子,在这个例子上做进一步的修改,来达到我们的目地。

在Passthru工程的 DriverEntry函数里面,我们都看见如下的代码:

NTSTATUS  DriverEntry(IN PDRIVER_OBJECT  DriverObject,  IN  PUNICODE_STRING  RegistryPath)
{
                NDIS_STATUS    Status;
  NDIS_PROTOCOL_CHARACTERISTICS  PChars;
  NDIS_MINIPORT_CHARACTERISTICS  MChars;
  PNDIS_CONFIGURATION_PARAMETER  Param;
  NDIS_STRING      Name;
  NDIS_HANDLE      WrapperHandle;


  UNICODE_STRING nameString, linkString; 
  UINT FuncIndex;
  PDEVICE_OBJECT MyDeviceObject; 
  PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

  Status = NDIS_STATUS_SUCCESS;
  
  //申请自旋锁 以到达资源共享的同步访问
  NdisAllocateSpinLock(&GlobalLock);

  //调用NdisMInitializeWrapper函数来保存在NdisWrapperHandle返回的句柄
  NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);

  do
  {
//调用NdisMInitializeWrapper函数来保存在WrapperHandle返回的句柄
    NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);

//对于MiniportCharacteristics组件,如果驱动程序不用导出MiniportXxx这样的函数,则必须赋值为NULL。
//如果要导出任何新版本的V4.0或V5.0的MiniportXxx函数,那么中间层驱动程序的主版本必须是V4.0,并且提供4.0或5.0版本的MiniportCharacteristics组件.
  NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));

  MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
  MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;

   /***************************************************
      下面开始注册中间层驱动程序的 MiniportXxx函数                   
    ***************************************************/
  MChars.HaltHandler             =   MPHalt;
  MChars.InitializeHandler       =   MPInitialize;
  MChars.QueryInformationHandler =   MPQueryInformation;
  MChars.SetInformationHandler   =   MPSetInformation;
  MChars.ResetHandler            =   MPReset;

  MChars.SendHandler             =   NULL;
  MChars.SendPacketsHandler      =   MPSendPackets;

  MChars.TransferDataHandler     =   MPTransferData;
  MChars.ReturnPacketHandler     =   MPReturnPacket;
  MChars.CheckForHangHandler     =   NULL;

#ifdef NDIS51_MINIPORT
  MChars.CancelSendPacketsHandler =  MPCancelSendPackets;
  MChars.PnPEventNotifyHandler    =  MPDevicePnPEvent;
  MChars.AdapterShutdownHandler   =  MPAdapterShutdown;
#endif // NDIS51_MINIPORT  


/*
传递上一步保存的句柄,并调用NdisIMRegisterLayeredMiniport函数来注册驱动程序的MiniportXxx系列函数。其中句柄NdisWrapperHandle是由先前的NdisMInitializeWrapper函数返回的。

当驱动程序调用NdisIMInitializeDeviceInstance函数,请求中间层驱动程序的MiniportInitialize函数对虚拟NIC进行初始化时,需要把句柄NdisWrapperHandle传入NDIS

当中间层驱动程序成功地绑定到一个或者多个NIC驱动程序上的时候, 或者是绑定到一个非NIC驱动程序上的时候也会调用NdisIMInitializeDeviceInstance函数。这样做使得中间层驱动程序可以初始化Miniport组件来接受虚拟NIC上的I/O请求
*/
           Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle, &MChars, sizeof(MChars), &DriverHandle);

            if (Status != NDIS_STATUS_SUCCESS)
       {
       break;
             }

#ifndef WIN9X
  NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
#endif

    
  //中间层驱动程序要做的事情:
  //初始化NDIS_PROTOCOL_CHARACTERISTICS类型的结构.  NDIS不再支持3.0版本的协议驱动.
  //能够使用4.0或5.0版本的ProtocolCharacteristic结构体,协议驱动必须支持PNP即插即用功能.
  NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
  PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
  NdisInitUnicodeString(&Name, L"Passthru");  
  PChars.Name = Name;

  /*******************************************************           
          下面开始注册中间层驱动程序的  ProtocolXxx函数                   
    这里主要是注册---下边界面向无连接的中间层驱动程序的ProtocolXxx函数    
        *******************************************************/

  PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
  PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
  PChars.SendCompleteHandler = PtSendComplete;
  PChars.TransferDataCompleteHandler = PtTransferDataComplete;
  
  PChars.ResetCompleteHandler = PtResetComplete;
  PChars.RequestCompleteHandler = PtRequestComplete;

  PChars.ReceiveHandler = PtReceive;
  PChars.ReceivePacketHandler = PtReceivePacket;
  PChars.ReceiveCompleteHandler = PtReceiveComplete;

  PChars.StatusHandler = PtStatus;
  PChars.StatusCompleteHandler = PtStatusComplete;

  PChars.BindAdapterHandler = PtBindAdapter;
  PChars.UnbindAdapterHandler = PtUnbindAdapter;
  PChars.UnloadHandler = PtUnloadProtocol;
  
  PChars.PnPEventHandler= PtPNPHandler;


  /*
  如果驱动程序随后要绑定到底层的NDIS驱动程序上,则调用NdisRegisterProtocol函数来注册驱动程序的ProtocolXxx函数。
  全局变量ProtHandle是在NDIS协议驱动里面的NdisRegisterProtocol函数里面初始化的,然后中间层驱动必须保存protHandle的值,并在将来NDIS中间层驱动程序的协议部分的函数调用中作为输入参数来传递.
  */

  NdisRegisterProtocol(&Status,  &ProtHandle,&PChars,
       sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

  if (Status != NDIS_STATUS_SUCCESS)
  {
    NdisIMDeregisterLayeredMiniport(DriverHandle);
                  break;
  }

//如果驱动程序导出了MiniportXxx和ProtocolXxx这一些列的函数,那么就调用NdisIMAssociateMiniport函数向NDIS通告有关驱动程序的微端口低边界和协议高边界信息
    NdisIMAssociateMiniport(DriverHandle, ProtHandle);
  }
  while (FALSE);

//----------------- 创建设备对象与符号连接----------------------------
  RtlInitUnicodeString(&nameString, L"\\Device\\MyPassthru" ); 
  RtlInitUnicodeString(&linkString, L"\\??\\MyPassthru"); 

  for(FuncIndex = 0; 
                    FuncIndex <=IRP_MJ_MAXIMUM_FUNCTION; 
                    FuncIndex++)
  {
    MajorFunction[FuncIndex] = NULL;
  }
      
  MajorFunction[IRP_MJ_CREATE]          =  MydrvDispatch;
  MajorFunction[IRP_MJ_CLOSE]           =  MydrvDispatch;
  MajorFunction[IRP_MJ_DEVICE_CONTROL]  =  MydrvDispatchIoctl;


  Status = NdisMRegisterDevice(
                    WrapperHandle, 
                    &nameString,
                    &linkString,
                    MajorFunction,
                    &MyDeviceObject,
                    &NdisDeviceHandle
                    );

  if(Status != STATUS_SUCCESS)
  {
    DbgPrint("NdisMRegisterDevice failed!\n");
  }


    
  return(Status);
}


然后,我们就开始实现相应的回调函数。 然而为了收、发网络数据包,对它们进行控制,我们基本上只会去修改以下的回调函数:
下面我把相关的函数的功能给罗列出来。


/***************************************************************
  MPSend函数的功能是:  发送单个数据包。                        
    若中间层驱动不支持MiniportSendPackets,那么MPSend函数必须实现。 
  
    参数说明:  
      MiniportAdapterContext    它是适配器。                    
      PacketArray              它是包描述符指针。              
      Flags                     它未被使用。                    
        
 ***************************************************************/
NDIS_STATUS
MPSend(
    IN NDIS_HANDLE          MiniportAdapterContext,
    IN PNDIS_PACKET        Packet,
    IN  UINT                      Flags
    )





/***************************************************************
   MPSendPackets函数的功能是:                                                 
  用于指定网络上传输数据包的包描述符指针数组。该函数可以用来发送多个数据包。而不是只发送单个数据包。除非中间层驱动程序绑定到低层WAN NIC驱动程序上,并提供MiniportWanSend函数,否则驱动程序应提供对MPSendPackets函数的支持, 而不是对MPSend函数的支持。
 
   参数说明:
      MiniportAdapterContext    它是适配器。 
    PacketArray               它是包描述符数组。                            
      NumberOfPackets           它是PacketArray的长度。                       
 
每个数据包发送完成后无论是否成功都要调用 NdisMSendComplete函数。让上层的协议驱动能够收到SendCompleteHandler来判断数据包的完成状态。        
 ***************************************************************/
VOID
MPSendPackets(
    IN  NDIS_HANDLE            MiniportAdapterContext,
    IN  PPNDIS_PACKET          PacketArray,
    IN  UINT                    NumberOfPackets
    )





/***************************************************************
  MPTransferData函数的功能:                             
    该函数用于传输在前视缓冲区中没有指示的接收数据包的剩余部分。前视缓冲区由      
    中间层驱动程序传递给 NdisMXxxIndicateReceive函数。这个被指示的数据包可以是    
    中间层驱动程序的ProtocolReceive函数或者是ProtocolReceivePackets处理程序接收的 
    转换数据包。                                   
    如果中间层驱动程序通过调用NdisMXxxIndicateReceive函数向上层驱动程序指示接收   
    数据包,那么MPTransferData函数必须提供。                                       
                                                                                  
    如果中间层通过调用驱动程序总是NdisMIndicateReceive函数向上层驱动程序指示接收 
    数据包,那么MPTransferData函数可以不必提供。即 NdisMIndicateReceivePacket指示
    接收数据包,那么传递给ProtocoltReceive函数   的前视缓冲区将总是获得完整的数据包。          
****************************************************************/
NDIS_STATUS
MPTransferData(
    OUT PNDIS_PACKET     Packet, //目的数据包
    OUT PUINT                   BytesTransferred,//复制了多少数据
    IN  NDIS_HANDLE         MiniportAdapterContext,//适配器结构体
    IN NDIS_HANDLE          MiniportReceiveContext,//上下文
    IN UINT                     ByteOffset,//指向拷贝数据包的偏移
    IN UINT                     BytesToTransfer//实际传输了多少字节的数据
    )





/***************************************************************
PtTransferDataComplete函数的功能:        
   它是MPTransferData()的异步完成函数。                                
  当ProtocolReceive函数需要调用NdisTransferData函数,那么我们必须实现
  PtTransferDataComplete的代码。

   当NdisTransferData调用之后,并且返回值是NDIS_STATUS_PENDING,在数据包传输完成了以后,会去调用PtTransferDataComplete函数用来表明一个数据包的传输完成。这时就会得到一个完整的数据包。 
**************************************************************/
VOID
PtTransferDataComplete(
    IN  NDIS_HANDLE         ProtocolBindingContext,
    IN  PNDIS_PACKET        Packet,
    IN  NDIS_STATUS         Status,
    IN  UINT                BytesTransferred
    )




/***************************************************************  
PtReceive函数的功能是:                                                                                  
    该函数以指向包含网络接收数据的前视缓冲区的指针为参数被调用执行。如果这个前视缓冲区没有包含完整的网络数据包,那么ProtocolReceive函数将以包描述符作为参数,调用NdisTransferData函数。                     
   当NdisTransferData调用之后,数据包传输完成了以后,会去调用
ProtocolTransferDataComplete函数以用来表明一个数据包的传输完成。这时就会得到一个完整的数据包。                                                  
                  
    
   如果低层驱动程序调用了 NdisMIndicateReceivePacket指示接收数据包,那么传递给PtReceive函数的前视缓冲区将总是获得完整的数据包。                             
   如果中间层驱动不需要完整的数据包时,可以调用NdisMXxxIndicateReceice函数向上通知,这样就省略了获取完整数据包的过程。
                            
 前视缓冲区:考虑数据包的接收,如果我们只需要看见数据内容的前几个字节(如TCP头)就可以决定这个包是否是本协议所需要处理的,那么显然下层驱动就没有必要提交整个数据包,只提供一个包开始的几个字节就可以了。      
                                                                                                          
  参数说明:                                 
 ProtocolBindingContext    在绑定是得到的绑定句柄,即它是在NdisOpenAdapter被调用时设置的。 
             
 MacReceiveContext    它指向一个不透明的环境变量,由底层NIC驱动传入,它用此句柄与从网络上收到的Packet关联。当调用NdisGetReceivePacket函数取得低层驱动上面的包描述符时,需要用到这个参数。当NDIS协议驱动的ProtocolReceive函数的实现中,可能要调用NdisTransferData函数,那么也会用到这个参数。  
 HeaderBuffer    它是一个以太网帧,就是以太网的包头。它是个虚拟的地址,只能在当前函数中有效,  它不能被存储而作为全局变量来使用。         
                                                           
 HeaderBufferSize          它是包头的长度,它的值一般为14                                               
 LookAheadBuffer           它是前视缓冲区指针。           
 LookAheadBufferSize       LookAheadBuffer的大小。     
                                                
 PacketSize                它是完整的数据包长度(不包括包头)。            
                                                     
  当PtReceive函数被调用了以后,系统将会去调用完成函数PtReceiveComplete  
                                                                                                                                   
  如果传递给PtReceive的数据是通过NdisMXxxIndicateReceive进行指示的,那么传递给PtReceive的前视缓冲区的长度不会超过用OID_GEN_CURRENT_LOOKAHEAD调用NdisRequest返回的值。                                      
                          
  如果PtReceive的调用执行在NdisMIndicateReceivePacket之前进行,那么底层驱动程序把包数组中的一个或者多个包状态设置为 NDIS_STATUS_RESOURCES,那么前视缓冲区的大小总是等于整个网络数据包的大小。所以中间层驱动程序可以不必调用NdisTransferData函数。     
***************************************************************/

NDIS_STATUS
PtReceive(
    IN  NDIS_HANDLE         ProtocolBindingContext,
    IN  NDIS_HANDLE         MacReceiveContext,
    IN  PVOID               HeaderBuffer,
    IN  UINT                HeaderBufferSize,
    IN  PVOID               LookAheadBuffer,
    IN  UINT                LookAheadBufferSize,
    IN  UINT                PacketSize
    )





/**************************************************************  
PtReceivePacket函数的功能是:                            
   这是一个可选函数。 如果中间层驱动程序所基于的NIC驱动程序指示的是数据包描述符指针数组,或者调用NdisMIndicateReceivePacket函数指示接收带外数据,那么驱动程序应该提供PtReceivePacket函数。 
 如果开发者不能够确定中间层驱动程序的执行环境,也应该提供该函数,因为在能够产生多包指示的底层NIC驱动程序上,中间层驱动程序将获得更好的性能。 
**************************************************************/
INT
PtReceivePacket(
    IN NDIS_HANDLE            ProtocolBindingContext,
    IN PNDIS_PACKET           Packet
    )


我们可以在这几个回调函数里面来处理、过滤、分析 捕捉到的数据包。防火墙软件一般也都是在这几个回调函数里面进行编程。

其它的回调函数的代码,我们基本上不用去修改。

NDIS  Passthru的例子很多,在网络上搜索一下,就有很多源代码例子,也有很多相关的技术说明。  



下面,我想重点的说明在Windows 7系统下,(当然是Win7 32/64位系统)如何做NDIS中间层驱动程序的开发,代码和之前老的Windows操作系统提供的Passthru例子的区别。




已标记关键词 清除标记
相关推荐
1 NDIS中间层驱动程序 2 1.1 NDIS中间层驱动程序(NDIS Intermediate Drivers)概述 2 1.2 NDIS中间层驱动程序的用途 4 1.3 NDIS中间层驱动程序的开发环境 4 2 NDIS中间层驱动程序的开发 4 2.1 可分页和可丢弃代码 4 2.2 共享资源的访问同步 5 2.3 中间层驱动程序的DriverEntry函数 5 2.3.1 注册NDIS中间层驱动程序 6 2.3.1.1 注册中间层驱动程序的Miniport 6 2.3.1.2 注册中间层驱动程序的协议 8 2.4 中间层驱动程序的动态绑定 11 2.4.1 打开中间层驱动程序下层的适配器 12 2.4.2 微端口(Miniport)初始化 12 2.4.3 中间层驱动程序查询和设置操作 13 2.4.3.1 发布设置和查询请求 14 2.4.3.2 响应设置和查询请求 15 2.4.4 作为面向连接客户程序注册中间层驱动程序 15 2.5 中间层驱动程序数据包管理 17 2.5.1.1 重用数据包 18 2.6 中间层驱动程序的限制 19 2.7 中间层驱动程序接收数据 19 2.7.1 下边界面向无连接的中间层驱动程序接收数据 19 2.7.1.1 在中间层驱动程序中实现ProtocolReceivePacket处理程序 20 2.7.1.2 在中间层驱动程序中实现ProtocolReceive处理程序 21 2.7.1.3 下边界面向无连接中间层驱动程序接收OOB数据信息 22 2.7.2 下边界面向连接的中间层驱动程序接收数据 22 2.7.2.1 在中间层驱动程序中实现ProtocolCoReceivePacket处理程序 23 2.7.2.2 在下边界面向连接的中间层驱动程序中接收OOB数据信息 23 2.7.3 向高层驱动程序指示接收数据包 23 2.8 通过中间层驱动程序传输数据包 23 2.8.1 传递介质相关信息 25 2.9 处理中间层驱动程序的PnP事件和PM事件 26 2.9.1 处理OID_PNP_XXX查询和设置 26 2.9.2 中间层驱动程序ProtocolPnPEvent处理程序的实现 27 2.9.3 处理规定的电源请求 28 2.9.3.1 睡眠状态的电源设置请求 28 2.9.3.2 工作状态的电源设置请求 29 2.10 中间层驱动程序复位操作 29 2.11 中间层驱动程序拆除绑定操作 30 2.12 中间层驱动程序状态指示 31 3 负载平衡和失效替换 31 3.1 关于LBFO 31 3.2 指定对LBFO的支持 32 3.3 在微端口驱动程序上实现LBFO 32 3.3.1 初始化微端口束 33 3.3.2 平衡微端口驱动程序的工作量 33 3.3.3 在主微端口失效后提升一个次微端口 34 4 安装网络组件 34 4.1 用于安装网络组件的组件和文件 34 4.2 创建网络INF文件 35 4.2.1 网络INFS文件名的约定 35 4.2.2 网络INF文件的版本节 35 4.2.3 网络INF文件的模型节 36 4.2.4 INF文件的DDInstall节 37 4.2.5 删除节 38 4.2.6 ControlFlags节 39 4.2.7 网络INF文件的add-registry-sections 39
本书的前身是《天书夜读——从汇编语言到Windows内核编程》和《寒江独钓——Windows内核安全编程》。与Windows客户端安全软件开发相关的驱动程序开发是本书的主题。书中的程序使用环境从32位到64位,从Windows XPWindows 8都有涉及,大部分程序不经过修改即可在Windows 10上运行。同时本书也深入浅出地介绍了进行内核安全编程所需要的操作系统、汇编等基础知识。 本书共分三篇,基础篇囊括了驱动开发的基础知识,降低了入门的难度;开发篇介绍了在实际工作中可能遇到的各种开发需求的技术实现,包括:串口的过滤、键盘的过滤、磁盘的虚拟、磁盘的过滤、文件系统的过滤与监控、文件系统透明加密、文件系统微过滤驱动、网络传输层过滤、Windows过滤平台、NDIS协议驱动NDIS小端口驱动NDIS中间层驱动、IA-32汇编基础、IA-32体系中的内存地址、处理器权限级别切换、IA-32体系结构中的中断和Windows内核挂钩;高级篇包含了汇编语言、操作系统原理、处理器体系架构相关的内容。本书是由长期从事这个行业的工程师自己写的,所以处处以实用为准。对细节的考究主要体现在对实际问题的解决,而不是知识的详尽程度上。 本书适合计算机安全软件从业人员、计算机相关专业院校学生以及有一定C语言和操作系统基础知识的编程爱好者阅读。
第1章 内核上机指导 2 1.1 下载和使用WDK 2 1.1.1 下载并安装WDK 2 1.1.2 编写第一个C文件 4 1.1.3 编译一个工程 5 1.2 安装与运行 6 1.2.1 下载一个安装工具 6 1.2.2 运行与查看输出信息 7 1.2.3 在虚拟机中运行 8 1.3 调试内核模块 9 1.3.1 下载和安装WinDbg 9 1.3.2 设置Windows XP调试执行 9 1.3.3 设置Vista调试执行 10 1.3.4 设置VMware的管道虚拟串口 11 1.3.5 设置Windows内核符号表 12 1.3.6 实战调试first 13 第2章 内核编程环境及其特殊性 16 2.1 内核编程的环境 16 2.1.1 隔离的应用程序 16 2.1.2 共享的内核空间 17 2.1.3 无处不在的内核模块 18 2.2 数据类型 19 2.2.1 基本数据类型 19 2.2.2 返回状态 19 2.2.3 字符串 20 2.3 重要的数据结构 21 2.3.1 驱动对象 21 2.3.2 设备对象 22 2.3.3 请求 24 2.4 函数调用 25 2.4.1 查阅帮助 25 2.4.2 帮助中有的几类函数 26 2.4.3 帮助中没有的函数 28 2.5 Windows驱动开发模型 29 2.6 WDK编程中的特殊点 30 2.6.1 内核编程的主要调用源 30 2.6.2 函数的多线程安全性 30 2.6.3 代码的中断级 32 2.6.4 WDK中出现的特殊代码 32 第3章 字符串与链表 35 3.1 字符串操作 35 3.1.1 使用字符串结构 35 3.1.2 字符串的初始化 36 3.1.3 字符串的拷贝 37 3.1.4 字符串的连接 38 3.1.5 字符串的打印 38 3.2 内存与链表 40 3.2.1 内存的分配与释放 40 3.2.2 使用LIST_ENTRY 41 3.2.3 使用长长整型数据 43 3.3 自旋锁 44 3.3.1 使用自旋锁 44 3.3.2 在双向链表中使用自旋锁 45 3.3.3 使用队列自旋锁提高性能 46 第4章 文件、注册表、线程 47 4.1 文件操作 47 4.1.1 使用OBJECT_ATTRIBUTES 47 4.1.2 打开和关闭文件 48 4.1.3 文件读/写操作 51 4.2 注册表操作 53 4.2.1 注册表键的打开 53 4.2.2 注册表键值的读 55 4.2.3 注册表键值的写 57 4.3 时间与定时器 58 4.3.1 获得当前“滴答”数 58 4.3.2 获得当前系统时间 58 4.3.3 使用定时器 59 4.4 线程与事件 62 4.4.1 使用系统线程 62 4.4.2 在线程中睡眠 63 4.4.3 使用同步事件 64 第5章 应用与内核通信 67 5.1 内核方面的编程 68 5.1.1 生成控制设备 68 5.1.2 控制设备的名字和符号链接 70 5.1.3 控制设备的删除 71 5.1.4 分发函数 72 5.1.5 请求的处理 73 5.2 应用方面的编程 74 5.2.1 基本的功能需求 74 5.2.2 在应用程序中打开与关闭设备 75 5.2.3 设备控制请求 75 5.2.4 内核中的对应处理 77 5.2.5 结合测试的效果 79 5.3 阻塞、等待与安全设计 80 5.3.1 驱动主动通知应用 80 5.3.2 通信接口的测试 81 5.3.3 内核中的缓冲区链表结构 83 5.3.4 输入:内核中的请求处理中的安全检查 84 5.3.5 输出处理与卸载清理 85 第6章 64位和32位内核开发差异 88 6.1 64位系统新增机制 88 6.1.1 WOW64子系统 88 6.1.2 PatchGuard技术 91 6.1.3 64位驱动的编译、安装与运行 91 6.2 编程差异 92 6.2.1 汇编嵌入变化 92 6.2.2 预处理与条件编译 93 6.2.3 数据结构调整 93 开 发 篇 第7章 串口的过滤 96 7.1 过滤的概念 96 7.1.1 设备绑定的内核API之一 97 7.1.2 设备绑定的内核API之二 98 7.1.3 生成过滤设备并绑定 98 7.1
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页