TA的每日心情 | 开心 2014-6-18 08:29 |
---|
签到天数: 14 天 [LV.3]偶尔看看II
滴水大师
 
- 积分
- 2345
|
在Win8系统下开发驱动程序,需要数字证书,还需要驱动签名认证。不能像XP下面那样疯狂滴耍流氓了。
由于Win8系统的内核做了大幅度的修改,它和XP系统的内核起了很大的变化,最显著的就是刚才说的:需要签名和证书。 还有就是:不能随意的HOOK SSDT了。
在开发NDIS驱动程序的时候,WDK开发包提供了一个新的框架,叫着NDIS Filter
NDIS Filter是一个例子工程。
假入我把WDK安装在E盘,那么这个工程代码就在:
C:\WinDDK\8600.16385.1\src\network\ndis\filter目录下。
把这个例子工程和原来的Passthru工程代码做比较,您会发现,原来需要导出来的2种类型的回调函数MiniportXXX和ProtocolXXX 在新的框架里面被全部隐藏起来了。
微软提供了新的函数。 一起来看看,微软提供了什么。
在这里,为了方便分析, 我把函数代码都做了功能注释,请大家一起看看。
代码如下:
- #pragma NDIS_INIT_FUNCTION(DriverEntry)
-
- #define LITTLE_ENDIAN (1)
- //
- // Global variables
- //
- NDIS_HANDLE FilterDriverHandle; // NDIS handle for filter driver
- NDIS_HANDLE FilterDriverObject;
- NDIS_HANDLE NdisFilterDeviceHandle = NULL;
- PDEVICE_OBJECT DeviceObject = NULL;
-
- FILTER_LOCK FilterListLock;
- LIST_ENTRY FilterModuleList;
- PWCHAR InstanceStrings = NULL;
-
- NDIS_FILTER_PARTIAL_CHARACTERISTICS DefaultChars = {
- { 0, 0, 0},
- 0,
- FilterSendNetBufferLists,
- FilterSendNetBufferListsComplete,
- NULL,
- FilterReceiveNetBufferLists,
- FilterReturnNetBufferLists
- };
-
- typedef struct in_addr {
- union {
- struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
- struct { USHORT s_w1,s_w2; } S_un_w;
- ULONG S_addr;
- } S_un;
- } IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
-
-
- #pragma push(1)
- typedef struct IP_HEADER
- {
-
- #if LITTLE_ENDIAN
- unsigned char ip_hl:4; /* 头长度 */
- unsigned char ip_v:4; /* 版本号 */
- #else
- unsigned char ip_v:4;
- unsigned char ip_hl:4;
- #endif
-
- unsigned char TOS; // 服务类型
-
- unsigned short TotLen; // 封包总长度,即整个IP包的长度
- unsigned short ID; // 封包标识,唯一标识发送的每一个数据报
- unsigned short FlagOff; // 标志
- unsigned char TTL; // 生存时间,就是TTL
- unsigned char Protocol; // 协议,可能是TCP、UDP、ICMP等
- unsigned short Checksum; // 校验和
- struct in_addr iaSrc; // 源IP地址
- struct in_addr iaDst; // 目的PI地址
-
- }IP_HEADER, *PIP_HEADER;
-
-
- typedef struct tcp_header
- {
- unsigned short src_port; //源端口号
- unsigned short dst_port; //目的端口号
- unsigned int seq_no; //序列号
- unsigned int ack_no; //确认号
- #if LITTLE_ENDIAN
- unsigned char reserved_1:4; //保留6位中的4位首部长度
- unsigned char thl:4; //tcp头部长度
- unsigned char flag:6; //6位标志
- unsigned char reseverd_2:2; //保留6位中的2位
- #else
- unsigned char thl:4; //tcp头部长度
- unsigned char reserved_1:4; //保留6位中的4位首部长度
- unsigned char reseverd_2:2; //保留6位中的2位
- unsigned char flag:6; //6位标志
- #endif
- unsigned short wnd_size; //16位窗口大小
- unsigned short chk_sum; //16位TCP检验和
- unsigned short urgt_p; //16为紧急指针
-
- }TCP_HEADER,*PTCP_HEADER;
-
-
- typedef struct udp_header
- {
- USHORT srcport; // 源端口
- USHORT dstport; // 目的端口
- USHORT total_len; // 包括UDP报头及UDP数据的长度(单位:字节)
- USHORT chksum; // 校验和
-
- }UDP_HEADER,*PUDP_HEADER;
- #pragma push()
-
-
- #define IP_OFFSET 0x0E
-
- //IP 协议类型
- #define PROT_ICMP 0x01
- #define PROT_TCP 0x06
- #define PROT_UDP 0x11
-
-
- USHORT UTIL_htons( USHORT hostshort )
- {
- PUCHAR pBuffer;
- USHORT nResult;
-
- nResult = 0;
- pBuffer = (PUCHAR )&hostshort;
-
- nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00) | (pBuffer[ 1 ] & 0x00FF);
-
- return( nResult );
- }
-
-
- /*UTIL_ntohs把网络字节顺序转换成主机字节顺序*/
- USHORT UTIL_ntohs( USHORT netshort )
- {
- return( UTIL_htons( netshort ) );
- }
-
-
-
- NTSTATUS
- DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
- {
- NDIS_STATUS Status;
- NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
- NDIS_STRING ServiceName;
- NDIS_STRING UniqueName;
- NDIS_STRING FriendlyName;
- BOOLEAN bFalse = FALSE;
-
- UNREFERENCED_PARAMETER(RegistryPath);
-
- DEBUGP(DL_TRACE,("===>DriverEntry...\n"));
-
- RtlInitUnicodeString(&ServiceName, FILTER_SERVICE_NAME);
- RtlInitUnicodeString(&FriendlyName, FILTER_FRIENDLY_NAME);
- RtlInitUnicodeString(&UniqueName, FILTER_UNIQUE_NAME);
- FilterDriverObject = DriverObject;
-
- do
- {
- NdisZeroMemory(&FChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS));
-
- /*
- 大多数的NDIS6.0数据结构中包含的对象头结构的成员,即NDIS_OBJECT_HEADER结构。
- 对象头有三个成员:类型,大小和修改。如果头信息是不正确的,那么调用NDIS6.0函数将失败。
- */
- FChars.Header.Type =
- NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
- FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
- FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;
-
- FChars.MajorNdisVersion = FILTER_MAJOR_NDIS_VERSION;
- FChars.MinorNdisVersion = FILTER_MINOR_NDIS_VERSION;
- FChars.MajorDriverVersion = 1;
- FChars.MinorDriverVersion = 0;
- FChars.Flags = 0;
-
- FChars.FriendlyName = FriendlyName;
- FChars.UniqueName = UniqueName;
- FChars.ServiceName = ServiceName;
-
-
- /******************************************************
- NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Mandatory例程
- ******************************************************/
- FChars.AttachHandler = FilterAttach;
- FChars.DetachHandler = FilterDetach;
- FChars.RestartHandler = FilterRestart;
- FChars.PauseHandler = FilterPause;
-
-
- /************************************************************
- NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且不能在运行时变更的例程
- *************************************************************/
- FChars.SetOptionsHandler = FilterRegisterOptions;
- FChars.SetFilterModuleOptionsHandler = FilterSetModuleOptions;
- FChars.OidRequestHandler = FilterOidRequest;
- FChars.OidRequestCompleteHandler = FilterOidRequestComplete;
- FChars.StatusHandler = FilterStatus;
- FChars.DevicePnPEventNotifyHandler = FilterDevicePnPEventNotify;
- FChars.NetPnPEventHandler = FilterNetPnPEvent;
- FChars.CancelSendNetBufferListsHandler = FilterCancelSendNetBufferLists;
-
-
-
- /**************************************************************
- DIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且能在运行时变更的例程。
-
- 下面这4个例程也被定义在NDIS_FILTER_PARTIAL_CHARACTERISTICS中,这个结构指定的
- 例程可以在运行时的FilterSetModuleOptions例程中调用NdisSetOptionHandles来改变。
- 如果过滤驱动要在例程中修改自身的一个特性,那么必须提供FilterSetModuleOptions例程。
- ****************************************************************/
- FChars.SendNetBufferListsHandler = FilterSendNetBufferLists;
- FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;
- FChars.ReturnNetBufferListsHandler = FilterReturnNetBufferLists;
- FChars.ReceiveNetBufferListsHandler = FilterReceiveNetBufferLists;
-
- ///
- FChars.CancelOidRequestHandler = FilterCancelOidRequest;
-
- DriverObject->DriverUnload = FilterUnload;
-
- FilterDriverHandle = NULL;
-
- FILTER_INIT_LOCK(&FilterListLock);
-
- InitializeListHead(&FilterModuleList);
-
- // 把Filter驱动注册给NDIS
- Status = NdisFRegisterFilterDriver(DriverObject,
- (NDIS_HANDLE)FilterDriverObject,
- &FChars,
- &FilterDriverHandle);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP(DL_WARN, ("MSFilter: Register filter driver failed.\n"));
- break;
- }
- //
- // Initilize spin locks
- //
-
- Status = FilterRegisterDevice();
-
- if (Status != NDIS_STATUS_SUCCESS)
- {
- NdisFDeregisterFilterDriver(FilterDriverHandle);
- FILTER_FREE_LOCK(&FilterListLock);
- DEBUGP(DL_WARN, ("MSFilter: Register device for the filter driver failed.\n"));
- break;
- }
-
-
- }
- while(bFalse);
-
-
- DEBUGP(DL_TRACE, ("<===DriverEntry, Status = %8x\n", Status));
- return Status;
-
- }
-
-
-
-
- //过滤驱动注册可选服务
- NDIS_STATUS
- FilterRegisterOptions(
- IN NDIS_HANDLE NdisFilterDriverHandle, //它指向了这个过滤驱动
- IN NDIS_HANDLE FilterDriverContext //它是这个驱动的上下文
- )
- {
- DEBUGP(DL_TRACE, ("===>FilterRegisterOptions\n"));
-
- ASSERT(NdisFilterDriverHandle == FilterDriverHandle);
- ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
-
- if ((NdisFilterDriverHandle != (NDIS_HANDLE)FilterDriverHandle) ||
- (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject))
- {
- return NDIS_STATUS_INVALID_PARAMETER;
- }
-
- DEBUGP(DL_TRACE, ("<===FilterRegisterOptions\n"));
-
- return (NDIS_STATUS_SUCCESS);
- }
-
-
-
- /***************************************************************
- FilterAttach函数的功能:
- Attaching状态表示:一个Filter Driver正准备附加一个Filter Module到一个驱动栈上。
- 一个过滤驱动进入Attaching状态下不能进行发送请求、接收指示、状态指示、OID请求操作。
-
- 当一个过滤驱动进入Attaching状态时,它可以:
- (1)创建一个环境上下文区域并且初始化一个缓冲区池以及其Filter Module特点的资源。
- (2)用NDIS 传来给Filter Attach的NdisFilterHandle作为输入来调用NdisFSetAttributes例程。
-
-
- Attach is complete
- 当Filter Module在Attaching状态下并且Filter Driver初始化了所有的Filter Module所需要的
- 所有资源时,Filter Module进入Paused状态。
-
-
- 参数说明:
- NdisFilterHandle 它用于所有过滤驱动中对Ndisxxx类例程的调用时引用指示这个过滤模块。
- FilterDriverContext 它由NdisFRegisterFilterDriver的FilterDriverContext来指定。
- AttachParameters 它是过滤模块的初始化参数结构体。
- **************************************************************/
- NDIS_STATUS
- FilterAttach(
- IN NDIS_HANDLE NdisFilterHandle,
- IN NDIS_HANDLE FilterDriverContext,
- IN PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters
- )
-
- {
- PMS_FILTER pFilter = NULL;
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
- NDIS_FILTER_ATTRIBUTES FilterAttributes;
- ULONG Size;
- BOOLEAN bFalse = FALSE;
-
- DEBUGP(DL_TRACE, ("===>FilterAttach: NdisFilterHandle %p\n", NdisFilterHandle));
-
- do
- {
- ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
- if (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject)
- {
- Status = NDIS_STATUS_INVALID_PARAMETER;
- break;
- }
-
- if ((AttachParameters->MiniportMediaType != NdisMedium802_3)
- && (AttachParameters->MiniportMediaType != NdisMediumWan))
- {
- DEBUGP(DL_ERROR, ("MSFilter: Doesn't support media type other than NdisMedium802_3.\n"));
-
- Status = NDIS_STATUS_INVALID_PARAMETER;
- break;
- }
-
- Size = sizeof(MS_FILTER) +
- AttachParameters->FilterModuleGuidName->Length +
- AttachParameters->BaseMiniportInstanceName->Length +
- AttachParameters->BaseMiniportName->Length;
-
- pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
- if (pFilter == NULL)
- {
- DEBUGP(DL_WARN, ("MSFilter: Failed to allocate context structure.\n"));
- Status = NDIS_STATUS_RESOURCES;
- break;
- }
-
- NdisZeroMemory(pFilter, sizeof(MS_FILTER));
-
- pFilter->FilterModuleName.Length = pFilter->FilterModuleName.MaximumLength = AttachParameters->FilterModuleGuidName->Length;
- pFilter->FilterModuleName.Buffer = (PWSTR)((PUCHAR)pFilter + sizeof(MS_FILTER));
-
- NdisMoveMemory(pFilter->FilterModuleName.Buffer,
- AttachParameters->FilterModuleGuidName->Buffer,
- pFilter->FilterModuleName.Length);
-
-
- pFilter->MiniportFriendlyName.Length = pFilter->MiniportFriendlyName.MaximumLength = AttachParameters->BaseMiniportInstanceName->Length;
- pFilter->MiniportFriendlyName.Buffer = (PWSTR)((PUCHAR)pFilter->FilterModuleName.Buffer + pFilter->FilterModuleName.Length);
-
- NdisMoveMemory(pFilter->MiniportFriendlyName.Buffer,
- AttachParameters->BaseMiniportInstanceName->Buffer,
- pFilter->MiniportFriendlyName.Length);
-
-
- pFilter->MiniportName.Length = pFilter->MiniportName.MaximumLength = AttachParameters->BaseMiniportName->Length;
- pFilter->MiniportName.Buffer = (PWSTR)((PUCHAR)pFilter->MiniportFriendlyName.Buffer +
- pFilter->MiniportFriendlyName.Length);
- NdisMoveMemory(pFilter->MiniportName.Buffer,
- AttachParameters->BaseMiniportName->Buffer,
- pFilter->MiniportName.Length);
-
- pFilter->MiniportIfIndex = AttachParameters->BaseMiniportIfIndex;
-
- pFilter->TrackReceives = TRUE;
- pFilter->TrackSends = TRUE;
- pFilter->FilterHandle = NdisFilterHandle;
-
-
- NdisZeroMemory(&FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
- FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
- FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
- FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
- FilterAttributes.Flags = 0;
-
-
- Status = NdisFSetAttributes(NdisFilterHandle,
- pFilter, //pFilter参数的功能是,为过滤模块指定环境上下文
- &FilterAttributes);
-
- if (Status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP(DL_WARN, ("MSFilter: Failed to set attributes.\n"));
- break;
- }
-
- pFilter->State = FilterPaused;
-
- FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse);
- InsertHeadList(&FilterModuleList, &pFilter->FilterModuleLink);
- FILTER_RELEASE_LOCK(&FilterListLock, bFalse);
-
- }
- while (bFalse);
-
- if (Status != NDIS_STATUS_SUCCESS)
- {
- if (pFilter != NULL)
- {
- FILTER_FREE_MEM(pFilter);
- }
- }
-
- DEBUGP(DL_TRACE, ("<===FilterAttach: Status %x\n", Status));
- return Status;
- }
-
-
-
-
- /**************************************************************
- FilterPause函数的功能:
- Paused状态:在这种状态下,Filter Driver不能执行接收和发送操作。
- 当FilterDriver执行FilterPause全程时它就进入了Pausing状态。
-
- Pausing状态:在这种状态下,Filter Driver要为一个Filter Module完成停止发送和接收
- 处理所需要的所有准备工作。
-
- 一个在Pausing状态的Filter Driver有如下的约束:
-
- (1)Filter Module不能发起任何新的接收指示,但可以传递下层驱动的接收指示。
- (2)如果有Filter Module发起的接收指示还没有完成,那么必须等到它们全部完成。有只当
- FilterReturnNetBufferLists完成所有外部接收指示后,暂停操作才能完成。
- (3)要返回任何未处理的由下层驱动引发的接收指示给NDIS,只有等到NdisFReturnNetBufferLists返回了所有未处理的接收指示后暂停操作才能完成。这里也可以排队缓冲这些未完成的接收指示。
- (4)立即用NdisFReturnNetBufferLists返回所有下层驱动新传来的接收指示,如果需要可以在返回之前制和排队这些接收指示。
- (5)不能发起任何新的发送请求。
- (6)如果有Filter Driver引的但NDIS还未完成的发送操作,必须等待它们完成。
- (8)应该在FilterSendNetBufferLists例程中立即调用NdisFSendNetBufferListsComplete返回那些新达到的发送请求。并且为每一个NET_BUFFER_LIST设置NDIS_STATUS_PAUSED返回状态。
- (8)这时可以使用NdisFIndicateStatus提供状态指示。
- (9)可以在FilterStatus中处理状态指示。
- (10)可以在FilterOidRequest里面处理OID请求。
- (11)可以发起一个OID操作。
- (12)不能释放分配的相关资源,和Filter Module相关的资源最好放在FilterDetach例程里面来释放。
- (13)如果有用于发送和接收的定时器那么要停止它。
-
- 当成功停止发送和接收操作后就必须完成暂停操作。暂停操作的完成可以是同步的也可以是异步的。
- 若返回值是NDIS_STATUS_SUCCESS则,是同步。
- 若是异步,则返回NDIS_STATUS_PENDING。那么还必须调用NdisFPauseComplete函数。
-
- 暂停操作完成了以后,Filter Module进入了Paused状态。这里它有如下的约束:
-
- (1)不能发起任何接收指示,但可以传递底层驱动发来的接收指示。
- (2)需要立即调用NdisFReturnNetBufferLists返回底层驱动的接收指示给NDIS,如果需要可以在返回之前复制和排队这些接收指示。
- (3)不能引发任何新的发送指示。
- (4)需要立即调用NdisFSendNetBufferListsComplete完成那些在FilterSendNetBufferLists中收到的发送请求,并为每一个NET_BUFFER_LIST设置NDIS_STATUS_PAUSED返回状态。
- (5)这时可以使用NdisFIndicateStatus发起状态指示。
- (6)可以在FilterStatus中进行状态指示处理。
- (8)可以在FilterOidRequest里面处理OID请求。
- (8)可以发起一个OID请求。
-
-
- 在Filter Module进行Pausing状态时NDIS不会发起其它PnP操作,比如:附加、分离、重启。只有当Filter Module进入了Paused状态后NDIS才能对它进行分离和重启操作。
- ***************************************************************/
- NDIS_STATUS
- FilterPause(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNDIS_FILTER_PAUSE_PARAMETERS PauseParameters
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)(FilterModuleContext);
- NDIS_STATUS Status;
- BOOLEAN bFalse = FALSE;
-
- UNREFERENCED_PARAMETER(PauseParameters);
-
- DEBUGP(DL_TRACE, ("===>NDISLWF FilterPause: FilterInstance %p\n", FilterModuleContext));
-
-
- FILTER_ASSERT(pFilter->State == FilterRunning);
-
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, bFalse);
- pFilter->State = FilterPausing;
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
-
-
- Status = NDIS_STATUS_SUCCESS;
-
- pFilter->State = FilterPaused;
-
- DEBUGP(DL_TRACE, ("<===FilterPause: Status %x\n", Status));
- return Status;
- }
-
-
-
-
- /***************************************************************
- FilterRestart函数的功能:
- 在Restarting状态下,一个Filter Driver必须为一个Filter Module完成重启发送和接收数据时
- 所需要的所有准备工作。
-
- Restart is complete
- 当Filter Module在Restarting状态下并且完成所有发送和接收所需要的准备工作时,Filter Module就进入了Running状态。
-
- 要启动一个Paused状态的Filter Module,如果有FilterSetModuleOptions就先调用它,接着调用FilterRestart。
-
- 当Filter Module在Restarting状态下,它可以:
- (1)完成任何正常的发送和接收所需要的准备工作。
- (2)可读写Filter Module的配置参数。
- (3)可以接收网络数据指示,拷贝和排队数据稍后只是给上层驱动或者丢弃数据。
- (4)不能发起任何新的接收指示。
- (5)应该立即调用NdisFSendNetBufferListsComplete例程来拒绝FilterSendNetBufferLists传来的发送的请求。应该设置每一个NET_BUFFER_LIST的完成状态为NDIS_STATUS_PAUSED
- (6)可以使用NdisFIndicateStatus例程进行状态指示。
- (8)可以控制OID请求操作。
- (8)不能发起任何新的发送请求。
- (9)应该调用NdisFReturnNetBufferLists返回所有新的接收指示。如果需要的话可以在接收指示返回之前拷贝它们。
- (10)可以制作OID请求发送给下层驱动设置或查询配置信息。
- (11)可以在FilterStatus中控制状态指示。
- (12)返回时指示 NDIS_STATUS_SUCCESS 或失败状态,如果不Filter Module不能启动返回了失败,而它又是一个Mandatory的Filter Driver 那个 NDIS将会结束这个驱动栈
- 在一个Filter Driver完成对发送和接收的重启后必须指示完成这个重启操作。
- Filter Driver的重启操作的完成可以是同步也可以是异步的,同步时返回 NDIS_STATUS_SUCCESS 异步时返回NDIS_STATUS_PENDING。如果返回的是 NDIS_STATUS_PENDING 就必须调用NdisFRestartComplete 例程在重启操作完成后。
- 在这种情况下,驱动需要传递给NdisFRestartComplete 一个固定状态(标识重启结果的成功或失败状态)。
-
- 重启操作完成Filter Module就进入了 Running状态,恢得一切正常的发送和接收外理。
- 在Filter Driver的FilterRestart例程执行的时候NDIS不会发起任即插即用操作,如附加,分离,暂停请求等等。Ndis可以在Filter Module进入Running状态后发起一个暂停请求。
- ***************************************************************/
- NDIS_STATUS
- FilterRestart(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNDIS_FILTER_RESTART_PARAMETERS RestartParameters
- )
-
- {
- NDIS_STATUS Status;
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; // BUGBUG, the cast may be wrong
- NDIS_HANDLE ConfigurationHandle = NULL;
-
-
- PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
- PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;
- NDIS_CONFIGURATION_OBJECT ConfigObject;
-
- DEBUGP(DL_TRACE, ("===>FilterRestart: FilterModuleContext %p\n", FilterModuleContext));
-
- FILTER_ASSERT(pFilter->State == FilterPaused);
-
- ConfigObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
- ConfigObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
- ConfigObject.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);
- ConfigObject.NdisHandle = FilterDriverHandle;
- ConfigObject.Flags = 0;
-
- Status = NdisOpenConfigurationEx(&ConfigObject, &ConfigurationHandle);
- if (Status != NDIS_STATUS_SUCCESS)
- {
-
- #if 0
- //
- // The code is here just to demonstrate how to call NDIS to write an eventlog. If drivers need to write
- // an event log.
- //
- PWCHAR ErrorString = L"Ndislwf";
-
- DEBUGP(DL_WARN, ("FilterRestart: Cannot open configuration.\n"));
- NdisWriteEventLogEntry(FilterDriverObject,
- EVENT_NDIS_DRIVER_FAILURE,
- 0,
- 1,
- &ErrorString,
- sizeof(Status),
- &Status);
- #endif
-
- }
-
-
- if (Status == NDIS_STATUS_SUCCESS)
- {
- NdisCloseConfiguration(ConfigurationHandle);
- }
-
- NdisRestartAttributes = RestartParameters->RestartAttributes;
-
-
- if (NdisRestartAttributes != NULL)
- {
- PNDIS_RESTART_ATTRIBUTES NextAttributes;
-
- ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);
-
- NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;
-
- NdisGeneralAttributes->LookaheadSize = 128;
-
- NextAttributes = NdisRestartAttributes->Next;
-
- while (NextAttributes != NULL)
- {
-
- NextAttributes = NextAttributes->Next;
- }
-
- }
-
-
- pFilter->State = FilterRunning;
-
-
- Status = NDIS_STATUS_SUCCESS;
-
- if (Status != NDIS_STATUS_SUCCESS)
- {
- pFilter->State = FilterPaused;
- }
-
-
- DEBUGP(DL_TRACE, ("<===FilterRestart: FilterModuleContext %p, Status %x\n", FilterModuleContext, Status));
- return Status;
- }
-
-
-
- /**************************************************************
- FilterDetach函数的功能:
- Detach状态:当Filter Driver从一个驱动栈上分离一个Filter Module时,将发生该事件。
- 在驱动栈上分离一个过滤模块时,NDIS会暂停这个驱动栈。这意味着NDIS已经使过滤模块进入
- 了Parse状态。即FilterPause函数先被调用了。
-
- 在这个例程中释放和这个过滤模块相关的环境上下文和其它资源。这个过程不能失败。
- 当FilterDetach函数返回以后,NDIS会重新启动被暂停的驱动栈。
-
- 参数说明:
- FilterDriverContext 它由NdisFRegisterFilterDriver的FilterDriverContext来指定。
- ************************************************************/
- VOID
- FilterDetach(
- IN NDIS_HANDLE FilterModuleContext
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- BOOLEAN bFalse = FALSE;
-
-
- DEBUGP(DL_TRACE, ("===>FilterDetach: FilterInstance %p\n", FilterModuleContext));
-
-
- FILTER_ASSERT(pFilter->State == FilterPaused);
-
-
- if (pFilter->FilterName.Buffer != NULL)
- {
- FILTER_FREE_MEM(pFilter->FilterName.Buffer);
- }
-
-
- FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse);
- RemoveEntryList(&pFilter->FilterModuleLink);
- FILTER_RELEASE_LOCK(&FilterListLock, bFalse);
-
-
- FILTER_FREE_MEM(pFilter);
-
-
- DEBUGP(DL_TRACE, ("<===FilterDetach Successfully\n"));
-
- return;
- }
-
-
-
-
- /**************************************************************
- 系统只会在调用FilterDetach()分离了所有和本Filter Driver相关的Filter Module以后,才会调用FilterUnload例程。
- ****************************************************************/
- VOID
- FilterUnload(
- IN PDRIVER_OBJECT DriverObject
- )
-
- {
- #if DBG
- BOOLEAN bFalse = FALSE;
- #endif
-
- UNREFERENCED_PARAMETER(DriverObject);
-
- DEBUGP(DL_TRACE, ("===>FilterUnload\n"));
-
-
- FilterDeregisterDevice();
- NdisFDeregisterFilterDriver(FilterDriverHandle);
-
- #if DBG
- FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse);
- ASSERT(IsListEmpty(&FilterModuleList));
-
- FILTER_RELEASE_LOCK(&FilterListLock, bFalse);
-
- #endif
-
- FILTER_FREE_LOCK(&FilterListLock);
-
- DEBUGP(DL_TRACE, ("<===FilterUnload\n"));
-
- return;
-
- }
-
-
-
- /***************************************************************
- FilterOidRequest函数的功能:
- Filter Module可以在Runnig状态、Restarting状态、Paused状态和Pauseing状态进行OID的控制和处理。
- Filter Driver可以处理上层驱动引发的OID请求,NDIS调用Filter Driver的FilterOidRequest例程来处理OID请求,Filter Driver需要调用NdisFOidRequest例程来转发请求给下层驱动。
-
- Filter Driver可以从FilterOidRequest同步和异步完成一个OID请求,分别返回NDIS_STATS_SUCCESS和NDIS_STATUS_PENDING即可。FilterOidRequest可以用同步的直接完成一个OID请求并返回一个错误状态。
-
- 如果FilterOidRequest返回NDIS_STATUS_PENDING,就必须在OID请求完成后调用
- NdisFOidRequestComplete来通知上层驱动求请求完成。在这种情况下,请求的结果通过
- NdisFOidRequestComplete的OidRequest参数返回给上层驱动,并通过Status参数返回请求完成的最终状态。
-
-
- 如果FilterOidRequest返回NDIS_STATUS_SUCCESS,通过FilterOidRequest的OidRequest参数返回一个查询结果到上层。这时不调用 NdisFOidRequestComplete例程。
-
-
- 要转发OID请求到下层驱动,Filter Driver必须调用NdisFOidRequest。如果一个OID请求不能被转发到下层驱动应该当立即返回。要完成一个请求且不转发可以直接返回NDIS_STATUS_SUCCESS或其它错误状态或返回 NDIS_STATUS_PENDING 后调用NdisFOidRequestComplete。
-
-
- 如果NdisFOidRequest返回NDIS_STATUS_PENDING,NDIS在OID请求完成后调用FilterOidRequestComplete来通知求请求完成在这种情况下,请求的结果通过NdisFOidRequestComplete的OidRequest参数返回给上层驱动,并通过 Status 参数返回请求完成的最终状态。
-
-
- 如果 NdisFOidRequest返回NDIS_STATUS_SUCCESS,通过NdisFOidRequest的OidRequest参数返回一个查询结果到上层。这时不调用FilterOidRequestComplete例程。
- 一个Filter Driver可以调用NdisFOidRequest引发OID请求在Restarting、Running、Pausing和Paused 状态。
-
- 注意:Filter Driver必须跟踪这个请求确保不在FilterOidRequestComplete中调用NdisFOidRequestComplete(因为请求是自己引发的不能传到上层)。
- ****************************************************************/
- NDIS_STATUS
- FilterOidRequest(IN NDIS_HANDLE FilterModuleContext,IN PNDIS_OID_REQUEST Request)
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- NDIS_STATUS Status;
- PNDIS_OID_REQUEST ClonedRequest=NULL;
- BOOLEAN bSubmitted = FALSE;
- PFILTER_REQUEST_CONTEXT Context;
- BOOLEAN bFalse = FALSE;
-
-
- DEBUGP(DL_TRACE, ("===>FilterOidRequest: Request %p.\n", Request));
-
- do
- {
- Status = NdisAllocateCloneOidRequest(pFilter->FilterHandle,
- Request,
- FILTER_TAG,
- &ClonedRequest);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone Request\n"));
- break;
- }
-
- Context = (PFILTER_REQUEST_CONTEXT)(&ClonedRequest->SourceReserved[0]);
- *Context = Request;
-
- bSubmitted = TRUE;
-
-
- ClonedRequest->RequestId = Request->RequestId;
-
- pFilter->PendingOidRequest = ClonedRequest;
-
-
- //Filter Driver可以调用NdisFOidRequest引发一个OID查询和设置请求给下层驱动。
- Status = NdisFOidRequest(pFilter->FilterHandle, ClonedRequest);
-
- if (Status != NDIS_STATUS_PENDING)
- {
-
- FilterOidRequestComplete(pFilter, ClonedRequest, Status);
- Status = NDIS_STATUS_PENDING;
- }
-
-
- }while (bFalse);
-
- if (bSubmitted == FALSE)
- {
- switch(Request->RequestType)
- {
- case NdisRequestMethod:
- Request->DATA.METHOD_INFORMATION.BytesRead = 0;
- Request->DATA.METHOD_INFORMATION.BytesNeeded = 0;
- Request->DATA.METHOD_INFORMATION.BytesWritten = 0;
- break;
-
- case NdisRequestSetInformation:
- Request->DATA.SET_INFORMATION.BytesRead = 0;
- Request->DATA.SET_INFORMATION.BytesNeeded = 0;
- break;
-
- case NdisRequestQueryInformation:
- case NdisRequestQueryStatistics:
- default:
- Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
- Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
- break;
- }
-
- }
- DEBUGP(DL_TRACE, ("<===FilterOidRequest: Status %8x.\n", Status));
-
- return Status;
-
- }
-
-
-
- /*************************************************************
- FilterCancelOidRequest函数的功能:
- NDIS调用FilterCancelOidRequest来取消一个OID请求,当NDIS调用FilterCancelOidRequest时,
- Filter Driver应该尽可能快的调用NdisFCancelOidRequest。
- *************************************************************/
- VOID
- FilterCancelOidRequest(
- IN NDIS_HANDLE FilterModuleContext,
- IN PVOID RequestId
- )
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- PNDIS_OID_REQUEST Request = NULL;
- PFILTER_REQUEST_CONTEXT Context;
- PNDIS_OID_REQUEST OriginalRequest = NULL;
- BOOLEAN bFalse = FALSE;
-
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, bFalse);
-
- Request = pFilter->PendingOidRequest;
-
- if (Request != NULL)
- {
- Context = (PFILTER_REQUEST_CONTEXT)(&Request->SourceReserved[0]);
-
- OriginalRequest = (*Context);
- }
-
- if ((OriginalRequest != NULL) && (OriginalRequest->RequestId == RequestId))
- {
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
-
- NdisFCancelOidRequest(pFilter->FilterHandle, RequestId);
- }
- else
- {
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
- }
-
-
- }
-
-
- VOID
- FilterOidRequestComplete(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNDIS_OID_REQUEST Request,
- IN NDIS_STATUS Status
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- PNDIS_OID_REQUEST OriginalRequest;
- PFILTER_REQUEST_CONTEXT Context;
- BOOLEAN bFalse = FALSE;
-
- DEBUGP(DL_TRACE, ("===>FilterOidRequestComplete, Request %p.\n", Request));
-
- Context = (PFILTER_REQUEST_CONTEXT)(&Request->SourceReserved[0]);
- OriginalRequest = (*Context);
-
-
- if (OriginalRequest == NULL)
- {
- filterInternalRequestComplete(pFilter, Request, Status);
- return;
- }
-
-
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, bFalse);
-
- ASSERT(pFilter->PendingOidRequest == Request);
- pFilter->PendingOidRequest = NULL;
-
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
-
- switch(Request->RequestType)
- {
- case NdisRequestMethod:
- OriginalRequest->DATA.METHOD_INFORMATION.OutputBufferLength = Request->DATA.METHOD_INFORMATION.OutputBufferLength;
- OriginalRequest->DATA.METHOD_INFORMATION.BytesRead = Request->DATA.METHOD_INFORMATION.BytesRead;
- OriginalRequest->DATA.METHOD_INFORMATION.BytesNeeded = Request->DATA.METHOD_INFORMATION.BytesNeeded;
- OriginalRequest->DATA.METHOD_INFORMATION.BytesWritten = Request->DATA.METHOD_INFORMATION.BytesWritten;
- break;
-
- case NdisRequestSetInformation:
- OriginalRequest->DATA.SET_INFORMATION.BytesRead = Request->DATA.SET_INFORMATION.BytesRead;
- OriginalRequest->DATA.SET_INFORMATION.BytesNeeded = Request->DATA.SET_INFORMATION.BytesNeeded;
- break;
-
- case NdisRequestQueryInformation:
- case NdisRequestQueryStatistics:
- default:
- OriginalRequest->DATA.QUERY_INFORMATION.BytesWritten = Request->DATA.QUERY_INFORMATION.BytesWritten;
- OriginalRequest->DATA.QUERY_INFORMATION.BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded;
- break;
- }
-
-
- (*Context) = NULL;
-
- NdisFreeCloneOidRequest(pFilter->FilterHandle, Request);
-
-
- /*
- 如果FilterOidRequest返回NDIS_STATUS_PENDING,就必须在OID请求完成后调用NdisFOidRequestComplete 来通知上层驱动求请求完成。在这种情况下,请求的结果通过NdisFOidRequestComplete的OidRequest参数返回给上层驱动,并通过Status参数返回请求完成的最终状态。
- 要转发OID请求到下层驱动,Filter Driver必须调用NdisFOidRequest。
- 如果一个OID请求不能被转发到下层驱动应该当立即返回。
- 要完成一个请求且不转发可以直接返回NDIS_STATUS_SUCCESS或其它错误状态
- 或返回NDIS_STATUS_PENDING后调用NdisFOidRequestComplete。
- */
-
- NdisFOidRequestComplete(pFilter->FilterHandle, OriginalRequest, Status);
-
- DEBUGP(DL_TRACE, ("<===FilterOidRequestComplete.\n"));
- }
-
-
-
-
- /*************************************************************
- FilterStatus函数的功能:
- 当下层驱动报告状态的时候 NDIS会调用它。此外,Filter Driver还可以自己引发一个状态指示。
-
- 当下层驱动调用一个状态指示例程时(NdisMIndicateStatusEx或NdisFIndicateStats),NDIS
- 会调用Filter Driver的FilterStatus例程。
-
- Filter Driver在FilterStatus中调用NdisFIndicateStatus传递一个状态指示给上层驱动。此外,还可以过滤状态指示(不用调用 NdisFIndicateStatus)或在调用 NdisFIndicateStatus之前修改状态信息。
-
-
- Filter Driver要自己引发一个状态报告,可以在NDIS未调用 FilterStatus的情况下调用NdisFIndicateStatus。在这种情况下,Filter Driver要设置 SourceHandle 成员为 FilteAttech 参数提供的NdisFilterHandle句柄。
- 如果一个状态指示是一个OID请求相关的(下层请求一个 OID 下层要做相应的状态指示),那么状态的DestinationHandle和RequestId成员要设置成上层的OID请求包携带的数据。
-
-
- Filter Driver调用NdisFIndicateStatus后NDIS会调用相邻上层的状态指示函数(ProtocolStatusEx或FilterStatus)。
- ****************************************************************/
- VOID
- FilterStatus(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNDIS_STATUS_INDICATION StatusIndication
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- #if DBG
- BOOLEAN bFalse = FALSE;
- #endif
-
- DEBUGP(DL_TRACE, ("===>FilterStaus, IndicateStatus = %8x.\n", StatusIndication->StatusCode));
-
- #if DBG
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, bFalse);
- ASSERT(pFilter->bIndicating == FALSE);
- pFilter->bIndicating = TRUE;
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
- #endif
-
-
- NdisFIndicateStatus(pFilter->FilterHandle, StatusIndication);
-
- #if DBG
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, bFalse);
- ASSERT(pFilter->bIndicating == TRUE);
- pFilter->bIndicating = FALSE;
-
- FILTER_RELEASE_LOCK(&pFilter->Lock, bFalse);
-
-
- #endif
-
- DEBUGP(DL_TRACE, ("<===FilterStaus.\n"));
-
- }
-
-
-
-
- /*
- Filter Driver提供FilterPnpEventNotify来接收NDIS传递的PnP和电源管理事件
- */
- VOID
- FilterDevicePnPEventNotify(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_DEVICE_PNP_EVENT NetDevicePnPEvent
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- NDIS_DEVICE_PNP_EVENT DevicePnPEvent = NetDevicePnPEvent->DevicePnPEvent;
- #if DBG
- BOOLEAN bFalse = FALSE;
- #endif
-
- DEBUGP(DL_TRACE, ("===>FilterDevicePnPEventNotify: NetPnPEvent = %p.\n", NetDevicePnPEvent));
-
- switch (DevicePnPEvent)
- {
-
- case NdisDevicePnPEventQueryRemoved:
- case NdisDevicePnPEventRemoved:
- case NdisDevicePnPEventSurpriseRemoved:
- case NdisDevicePnPEventQueryStopped:
- case NdisDevicePnPEventStopped:
- case NdisDevicePnPEventPowerProfileChanged:
- case NdisDevicePnPEventFilterListChanged:
-
- break;
-
- default:
- DEBUGP(DL_ERROR, ("FilterDevicePnPEventNotify: Invalid event.\n"));
- FILTER_ASSERT(bFalse);
-
- break;
- }
-
- //Filter Driver要下层驱动转发收到的事件,转发事件要用到NdisFDevicePnPEventNotify例程
- NdisFDevicePnPEventNotify(pFilter->FilterHandle, NetDevicePnPEvent);
-
- DEBUGP(DL_TRACE, ("<===FilterDevicePnPEventNotify\n"));
-
- }
-
-
-
-
-
- /*
- Filter Driver提供了FilterNetPnpEvent例程来处理网络Pnp和电源管理事件通知。
- */
- NDIS_STATUS
- FilterNetPnPEvent(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_PNP_EVENT_NOTIFICATION NetPnPEventNotification
- )
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
-
- //Filter Driver需要转发网络PnP和电源管理事件给上层驱动。转发这些事件是通NdisFNetPnpEvent来完成的。
- Status = NdisFNetPnPEvent(pFilter->FilterHandle, NetPnPEventNotification);
-
- return Status;
- }
-
-
-
-
- /**************************************************************
- FilterSendNetBufferListsComplete函数的功能:
- NDIS调用 FilterSendNetBufferListsComplete 把发送的结构和数据返还给 Filter Driver。NDIS可以收集多次NdisFSendNetBufferLists发送的结构和数据形成一个单链表传递给FilterSendNetBufferListsComplete。除非到NDIS调用FilterSendNetBufferListsComplete,否则一个发送请求的当前状态总是未知的。
-
- 一个过滤驱动是不能在NDIS调用FilterSendNetBufferListsComplete返回结构之前对NET_BUFFER_LIST和其关联的数据做检查的。FilterSendNetBufferListsComplete要完成一个发送请求完成后的任何必要的后继处理。当NDIS调用FilterSendNetBufferListsComplete时,Filter Driver就重新获地对结构及结构相关资源的所有权。可以在 FilterSendNetBufferListsComplete中释放相关的资源和准备下一个NdisFSendNetBufferLists调用。
-
- NDIS总是按照过滤驱动调用NdisFSendNetBufferLists提交的顺序传递给下层驱动,但是回返FilterSendNetBufferListsComplete 的顺序则是任意的。Filter Driver可以请求一个回环发送请求,只要把NdisFSendNetBufferLists的SendFlags设置成NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK就行了。NDIS会引发一个包含发送数据的接收包指示。
-
-
- 一个Filter Driver应该对自己引发的发送请求保持跟踪并确保在完成时不调用NdisFSendNetBufferComplete例程。
- **************************************************************/
- VOID
- FilterSendNetBufferListsComplete(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_BUFFER_LIST NetBufferLists,
- IN ULONG SendCompleteFlags
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- ULONG NumOfSendCompletes = 0;
- BOOLEAN DispatchLevel;
- PNET_BUFFER_LIST CurrNbl;
-
- DEBUGP(DL_TRACE, ("===>SendNBLComplete, NetBufferList: %p.\n", NetBufferLists));
-
-
- if (pFilter->TrackSends)
- {
- CurrNbl = NetBufferLists;
- while (CurrNbl)
- {
- NumOfSendCompletes++;
- CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
-
- }
- DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
- pFilter->OutstandingSends -= NumOfSendCompletes;
- FILTER_LOG_SEND_REF(2, pFilter, PrevNbl, pFilter->OutstandingSends);
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- }
-
- NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);
-
- DEBUGP(DL_TRACE, ("<===SendNBLComplete.\n"));
- }
-
-
-
-
- /*************************************************************
- FilterSendNetBufferLists函数的功能:
- NDIS调用一个Filter Driver的FilterSendNetBufferLists例程来过滤上层驱动的发送请求。Filter Driver不能改变其它驱动传来的NET_BUFFER_LIST结构中的SourceHandle成员的值。它可以过滤数据并发送过滤的数据到下层驱动。
- 对每一个提交到FilterSendNetBufferLists的NDIS_BUFFER_LIST,我们可做下面的操作。
-
- 1)可以把缓冲区通过 NdisFSendBufferLists 传递给下层驱动,NDIS 保证上下文空间对FilterDriver的有效性。过滤驱动可以在发送前修改缓冲区的内容。可以像处理自己引发的发送请求的缓冲区一样处理这个缓冲区。
- 2)可以调用 NdisFSendNetBufferListsComplete 拒绝传递这个包
- 3)排队缓冲区内容到本地的供以后处理。例如要在一定超时后处理或要接收到特定包后才处理等。如果支持这种处理方式就要支持取消请求的操作。
- 4)可以拷贝缓冲区并引发一个发送请求。它类似自己引发一个发送请求,但必须先调用 NdisFSendNetBufferComplete返回上层驱动的缓冲区。
-
- 发送请求在驱动栈继续完成,当一个微端口驱动调用NdisMSendNetBufferListsComplete完成一个发送请求时,NDIS会调用微端口
- 驱动之上最近的Filter Driver的FilterSendNetBufferLists例程。
-
- 在一个发送操作完成后,Filter Driver可以做在FilterSendNetBufferLists中所有修改的相反操作。FilterSendNetBufferListsComplete返回一个NET_BUFFER_LIST结构的单链表和发送请求的最终状态给上层的驱动。当最顶层的 Filter Module的FilterSendNetBufferListsComplete被调用完成后NDIS会调用引发发送请求的协议驱动的ProtocolSendNetBufferListsComplete。如果Filter Driver不提供FilterSendNetBufferLists它还是可以引发一个发送操作的,但它必须提供一个FilterSendNetBufferListsComplete并且不能在这个例程里把这个事件传递给上层驱动。
-
- 一个Filter Driver可以传递或过滤一个上层驱动的回环请求,要传递一个回环请求,NDIS会设置FilterSendNetBufferLists的SendFlags参数为NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,Filter Driver在调用NdisFSendNetBufferLists时把这个标记传给它即可。在回环请求的情况下NDIS会指示一个包含发送数据的接收包。
-
- 通常情况下,如果一个Filter Driver修改的任何行为不是NDIS提供的标准服务,那么它应该当自己为NDIS提供相应的服务。例如,如果一个Filter Driver修改了一个硬件地址请求,就必须处理直接到这个新地址回环包。在这种情况下, 因为Filter Driver已经更改了地址NDIS是不能提供一个回环服务的。
- 还有就是如果Filter Driver设置了混杂模式那它就不能传递额外的数据给上层接收。
- **************************************************************/
-
- VOID
- FilterSendNetBufferLists(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_BUFFER_LIST NetBufferLists,
- IN NDIS_PORT_NUMBER PortNumber,
- IN ULONG SendFlags
- )
-
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- PNET_BUFFER_LIST CurrNbl;
- BOOLEAN DispatchLevel;
- BOOLEAN bFalse = FALSE;
-
- DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists));
-
- do
- {
-
- DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
-
- #if DBG
-
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
-
- if (pFilter->State != FilterRunning)
- {
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
-
- CurrNbl = NetBufferLists;
- while (CurrNbl)
- {
- NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
- CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
- }
- NdisFSendNetBufferListsComplete(pFilter->FilterHandle,
- NetBufferLists,
- DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
- break;
-
- }
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- #endif
-
- /******************************************************/
-
- //在这里添加我们的代码
-
- /******************************************************/
-
- if (pFilter->TrackSends)
- {
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
- CurrNbl = NetBufferLists;
- while (CurrNbl)
- {
- pFilter->OutstandingSends++;
- FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);
-
- CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
- }
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- }
-
-
- NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
-
-
- }
- while (bFalse);
-
- DEBUGP(DL_TRACE, ("<===SendNetBufferList. \n"));
- }
-
-
-
-
- /*************************************************************
- FilterReturnNetBufferLists函数的功能:
- 如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists
- 返回指示数据。在这种情况下 Filter Driver失去了对NET_BUFFER_LIST的所有权,直到FilterReturnNetBufferLists被调用。
-
- Filter Driver调用NdisFIndicateNetBufferLists 传递接收指示给驱动栈上的上层驱动,如果上层驱动保留了对缓冲区(NET_BUFFER_LIST)的所有权,NDIS会调用Filter Driver的FilterReturnNetBufferLists 例程。
-
- 在FilterReturnNetBufferLists中应该撤消在接收路径上(如在 FilterReciveNetBufferLists中做的一些处理)的操作。当最底层的Filter Module完成对缓冲区(NET_BUFFER_LIST)的处理后,NDIS把缓冲区返回给微端口驱动。如果FilterReceiveNetBufferLists的ReceiveFlags没有设置NDIS_RECEIVE_FLAGS_RESOURCES标记, FilterDriver调用NdisFReturnNetBufferList返回这个缓冲区数据,如果设置了FilterReceiveNetBufferLists直接返回时就把缓冲区返还给了下层微端口驱动。
- ***************************************************************/
- VOID
- FilterReturnNetBufferLists(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_BUFFER_LIST NetBufferLists,
- IN ULONG ReturnFlags
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- PNET_BUFFER_LIST CurrNbl = NULL;
- UINT NumOfNetBufferLists = 0;
- BOOLEAN DispatchLevel;
- ULONG Ref;
-
- DEBUGP(DL_TRACE, ("===>ReturnNetBufferLists, NetBufferLists is %p.\n", NetBufferLists));
-
- if (pFilter->TrackReceives)
- {
- while (CurrNbl)
- {
-
- NumOfNetBufferLists ++;
- CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
- }
- }
- NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);
-
- if (pFilter->TrackReceives)
- {
- DispatchLevel = NDIS_TEST_RETURN_AT_DISPATCH_LEVEL(ReturnFlags);
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
-
- pFilter->OutstandingRcvs -= NumOfNetBufferLists;
- Ref = pFilter->OutstandingRcvs;
- FILTER_LOG_RCV_REF(3, pFilter, NetBufferLists, Ref);
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- }
-
-
- DEBUGP(DL_TRACE, ("<===ReturnNetBufferLists.\n"));
-
- }
-
-
-
- /***************************************************************
- FilterReceiveNetBufferLists函数的功能:
- Filter Driver调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。这个函数通过NET_BUFFER_LIST结构给上层驱动指示数据。Filter Driver可以从池中分配这个结构。如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为 NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。在这种情况下Filter Driver失去了对NET_BUFFER_LIST的所有权直到FilterReturnNetBufferLists被调用。如果Filter Driver在调用NdisFIndicateReceiveNetBufferLists时设置ReceiveFlags为NDIS_RECEIVE_FLAGS_RESOURCES,在函数返回后Filter Driver会立即恢复对NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回,因为NDIS在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。
-
- 注意: 一个Filter Driver应该跟踪自己引发的接收指示确保它在FilterReturnNetBufferLists
- 中不调用NdisFReturnNetBufferLists。
- ***************************************************************/
- VOID
- FilterReceiveNetBufferLists(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNET_BUFFER_LIST NetBufferLists,
- IN NDIS_PORT_NUMBER PortNumber,
- IN ULONG NumberOfNetBufferLists,
- IN ULONG ReceiveFlags
- )
-
- {
-
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- BOOLEAN DispatchLevel;
- ULONG Ref;
- BOOLEAN bFalse = FALSE;
-
-
- #if DBG
- ULONG ReturnFlags;
- #endif
-
- DEBUGP(DL_TRACE, ("===>ReceiveNetBufferList: NetBufferLists = %p.\n", NetBufferLists));
- do
- {
-
- DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);
- #if DBG
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
-
- if (pFilter->State != FilterRunning)
- {
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
-
- if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
- {
- ReturnFlags = 0;
- if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags))
- {
- NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
- }
-
- NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);
- }
- break;
- }
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- #endif
-
- ASSERT(NumberOfNetBufferLists >= 1);
-
-
- /*--------------------------------------------------------------------------------------*/
-
- //在这里添加我们的代码
-
-
- /*---------------------------------------------------------------------------------------*/
-
-
- if (pFilter->TrackReceives)
- {
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
- pFilter->OutstandingRcvs += NumberOfNetBufferLists;
- Ref = pFilter->OutstandingRcvs;
-
- FILTER_LOG_RCV_REF(1, pFilter, NetBufferLists, Ref);
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- }
-
-
- /************************************************************
- 调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。
-
- 如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists 返回指示数据。
-
- 如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的ReceiveFlags值为
- NDIS_RECEIVE_FLAGS_RESOURCES,那么在函数返回后Filter Driver会立即恢复对
- NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回。
- 在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。
- ************************************************************/
- NdisFIndicateReceiveNetBufferLists(
- pFilter->FilterHandle,
- NetBufferLists,
- PortNumber,
- NumberOfNetBufferLists,
- ReceiveFlags);
-
-
- if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags) && pFilter->TrackReceives)
- {
- FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
- pFilter->OutstandingRcvs -= NumberOfNetBufferLists;
- Ref = pFilter->OutstandingRcvs;
- FILTER_LOG_RCV_REF(2, pFilter, NetBufferLists, Ref);
- FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
- }
-
- } while (bFalse);
-
- DEBUGP(DL_TRACE, ("<===ReceiveNetBufferList: Flags = %8x.\n", ReceiveFlags));
-
- }
-
-
-
- /**************************************************************
- FilterCancelSendNetBufferLists函数的功能:
- 过滤驱动调用NDIS_SET_NET_BUFFER_LIST_CANCEL_ID宏为每一个NET_BUFFER_LIST标记一个取消Id。
- 在为网络数据分配取消ID之前,必须先调用NdisGenratePartialCanceId获得取消ID的高字节。
- 这是为了确保不是驱动不会把一个取消ID分配给两个驱动驱动通常在DriverEntry调用
- NdisGenratePartialCanceld,但是驱动可以在不同的时间多次调用它来获得多个取消ID。
- 要取消被标记过取消ID且正在传输的数据,驱动可以调用NdisFCancelSendNetBufferLists例程
- 来完成。要获得取消ID可以用NDIS_GET_NET_BUFFER_LIST_CANCEL_ID宏来完成。
-
- 如果一个Filter Driver对所有发送的NET_BUFFER_LIST标记了相同的取消ID那它可以用一个
- NdisFCancelSendNetBufferLists来取消所有的发送请求。如果把一部发送请求的NET_BUFFER_LIST标记相同的取消ID那么就可以调用一次NdisFCancelSendNetBufferLists来取消这部分发送请求。
-
- 在实现这个功能时NDIS会调用下层驱动的取消发送功能。中断正在执行的发送任务后,下层驱动会
- 调用发送完成全程(如:NdisMSendNetBufferListComplete)返回指定的NET_BUFFER_LIST结构并指定 返回状态为 NDIS_STATUS_CANCELLED, NDIS依次调用Filter Driver的FilterSendNetBufferListsComplete例程。在FilterSendNetBufferListsComplete中要用NDIS_SET_NET_BUFFER_LIST_CANCEL_ID设置取消的NET_BUFFER_LIST
- 的取消ID 为 NULL,这样是为了防止这个ID,在 NET_BUFFER_LIST被再次分配时使用。
-
-
- 上层驱动在取消一个未完成的发送请求时也必须对这个发送请求的 NET_BUFFER_LIST结构设定取消ID。
- NDIS会传递给Filter Driver的FilterCancelSendNetBufferLists一个取消ID来取消发送请求的
- NET_BUFFER_LIST发送。FilterCanCelSendNetBufferLists下执行下列操作。
- 1)遍历 Filter Driver的发送队列,用 NDIS_GET_NET_BUFFER_LSIT_CANCEL_ID获得队列中NET_BUFFER_LIST的取消ID与FilterCancelSendBufferLists的取消ID比较。
- 2)移除队列中取消 ID 和 FilterCancelSentBufferLists中取消ID相同的元素。
- 3)调用 NdisFSendNetBufferListsComplete来完成这些NET_BUFFER_LIST并设定返回状
- 态为NDIS_STATUS_CANCELLED。
- 4)调用NdisFCancelSendNetBufferLists传递取消发送请求给下层驱动。传递取消ID给下层驱动就Filter Driver取消自己引发的发关请求一样。
- *************************************************************/
- VOID
- FilterCancelSendNetBufferLists(
- IN NDIS_HANDLE FilterModuleContext,
- IN PVOID CancelId
- )
-
- {
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
-
- NdisFCancelSendNetBufferLists(pFilter->FilterHandle,CancelId);
- }
-
-
-
-
- /**************************************************************
- FilterSetModuleOptions函数的功能:
- 必须要在初始化时为驱动注册FilterSetModuleOptions例程,驱动可以在这个例程中初始化
- NDIS_FILTER_PARTIAL_CHARACTERISTICS结构来调用NdisSetOptionalHandlers来完成必变。
- 这个例程如果存在那么在调用Filter Driver的FilterRestart例程之前调用它。
- ***************************************************************/
- NDIS_STATUS
- FilterSetModuleOptions(
- IN NDIS_HANDLE FilterModuleContext
- )
- {
-
- PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
- NDIS_FILTER_PARTIAL_CHARACTERISTICS OptionalHandlers;
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
- BOOLEAN bFalse = FALSE;
-
-
- if (bFalse)
- {
- UINT i;
-
-
- pFilter->CallsRestart++;
-
- i = pFilter->CallsRestart % 8;
-
- pFilter->TrackReceives = TRUE;
- pFilter->TrackSends = TRUE;
-
- NdisMoveMemory(&OptionalHandlers, &DefaultChars, sizeof(OptionalHandlers));
- OptionalHandlers.Header.Type = NDIS_OBJECT_TYPE_FILTER_PARTIAL_CHARACTERISTICS;
- OptionalHandlers.Header.Size = sizeof(OptionalHandlers);
- switch (i)
- {
-
- case 0:
- OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
- pFilter->TrackReceives = FALSE;
- break;
-
- case 1:
-
- OptionalHandlers.ReturnNetBufferListsHandler = NULL;
- pFilter->TrackReceives = FALSE;
- break;
-
- case 2:
- OptionalHandlers.SendNetBufferListsHandler = NULL;
- pFilter->TrackSends = FALSE;
- break;
-
- case 3:
- OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
- pFilter->TrackSends = FALSE;
- break;
-
- case 4:
- OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
- OptionalHandlers.ReturnNetBufferListsHandler = NULL;
- break;
-
- case 5:
- OptionalHandlers.SendNetBufferListsHandler = NULL;
- OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
- break;
-
- case 6:
-
- OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
- OptionalHandlers.ReturnNetBufferListsHandler = NULL;
- OptionalHandlers.SendNetBufferListsHandler = NULL;
- OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
- break;
-
- case 8:
- break;
- }
- Status = NdisSetOptionalHandlers(pFilter->FilterHandle, (PNDIS_DRIVER_OPTIONAL_HANDLERS)&OptionalHandlers );
- }
- return Status;
- }
-
-
-
- NDIS_STATUS
- filterDoInternalRequest(
- IN PMS_FILTER FilterModuleContext,
- IN NDIS_REQUEST_TYPE RequestType,
- IN NDIS_OID Oid,
- IN PVOID InformationBuffer,
- IN ULONG InformationBufferLength,
- IN ULONG OutputBufferLength, OPTIONAL
- IN ULONG MethodId, OPTIONAL
- OUT PULONG pBytesProcessed
- )
-
- {
- FILTER_REQUEST FilterRequest;
- PNDIS_OID_REQUEST NdisRequest = &FilterRequest.Request;
- NDIS_STATUS Status;
- BOOLEAN bFalse;
-
-
- bFalse = FALSE;
- NdisZeroMemory(NdisRequest, sizeof(NDIS_OID_REQUEST));
-
- NdisInitializeEvent(&FilterRequest.ReqEvent);
-
- NdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
- NdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
- NdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST);
- NdisRequest->RequestType = RequestType;
-
- switch (RequestType)
- {
- case NdisRequestQueryInformation:
- NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
- NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =InformationBuffer;
-
- NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
-
- break;
-
- case NdisRequestSetInformation:
- NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
- NdisRequest->DATA.SET_INFORMATION.InformationBuffer =InformationBuffer;
-
- NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =InformationBufferLength;
-
- break;
-
- case NdisRequestMethod:
- NdisRequest->DATA.METHOD_INFORMATION.Oid = Oid;
- NdisRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;
- NdisRequest->DATA.METHOD_INFORMATION.InformationBuffer = InformationBuffer;
-
- NdisRequest->DATA.METHOD_INFORMATION.InputBufferLength = InformationBufferLength;
-
- NdisRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength;
- break;
-
-
-
- default:
- FILTER_ASSERT(bFalse);
- break;
- }
-
- NdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID;
-
- Status = NdisFOidRequest(FilterModuleContext->FilterHandle,NdisRequest);
-
-
- if (Status == NDIS_STATUS_PENDING)
- {
-
- NdisWaitEvent(&FilterRequest.ReqEvent, 0);
- Status = FilterRequest.Status;
- }
-
-
- if (Status == NDIS_STATUS_SUCCESS)
- {
- if (RequestType == NdisRequestSetInformation)
- {
- *pBytesProcessed = NdisRequest->DATA.SET_INFORMATION.BytesRead;
- }
-
- if (RequestType == NdisRequestQueryInformation)
- {
- *pBytesProcessed = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
- }
-
- if (RequestType == NdisRequestMethod)
- {
- *pBytesProcessed = NdisRequest->DATA.METHOD_INFORMATION.BytesWritten;
- }
-
- if (RequestType == NdisRequestMethod)
- {
- if (*pBytesProcessed > OutputBufferLength)
- {
- *pBytesProcessed = OutputBufferLength;
- }
- }
- else
- {
-
- if (*pBytesProcessed > InformationBufferLength)
- {
- *pBytesProcessed = InformationBufferLength;
- }
- }
- }
-
-
- return (Status);
- }
-
-
-
- VOID
- filterInternalRequestComplete(
- IN NDIS_HANDLE FilterModuleContext,
- IN PNDIS_OID_REQUEST NdisRequest,
- IN NDIS_STATUS Status
- )
-
-
- {
- PFILTER_REQUEST FilterRequest;
-
- UNREFERENCED_PARAMETER(FilterModuleContext);
-
- FilterRequest = CONTAINING_RECORD(NdisRequest, FILTER_REQUEST, Request);
-
- FilterRequest->Status = Status;
-
- NdisSetEvent(&FilterRequest->ReqEvent);
- }
|
|