轉:Windows8內核模式下開發NDIS應用-NDIS Filter講解

http://blog.csdn.net/itcastcpp/article/details/7752075網絡

在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
}; tcp

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
{ui

#if LITTLE_ENDIAN
unsigned char ip_hl:4; /* 頭長度 */
unsigned char ip_v:4; /* 版本號 */
#else
unsigned char ip_v:4;
unsigned char ip_hl:4;
#endifspa

unsigned char TOS; // 服務類型.net

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);}

相關文章
相關標籤/搜索