ispsh 发表于 2015-5-16 08:21:21

NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别

  标 题: 【原创】NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别
作 者: tianhz
时 间: 2011-07-21,14:58:04
链 接: http://bbs.pediy.com/showthread.php?t=137545

NDIS中间层驱动的开发在Win7系统上和Windows XP系统上有差别。
我把NDIS中间层的讨论分成2块。 windows 7系统和Windows XP系统。
(一)在 Windows XP系统上进行开发
平时很多朋友包括我在内,我们都在XP系统上使用NDIS5.1的框架来进行程序开发。我们都使用
Microsoft WDK提供的 NDIS 的 Passthru例子,在这个例子上做进一步的修改,来达到我们的目地。
在Passthru工程的 DriverEntry函数里面,我们都看见如下的代码:
NTSTATUSDriverEntry(IN PDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegistryPath)
{
                NDIS_STATUS    Status;
NDIS_PROTOCOL_CHARACTERISTICSPChars;
NDIS_MINIPORT_CHARACTERISTICSMChars;
PNDIS_CONFIGURATION_PARAMETERParam;
NDIS_STRING      Name;
NDIS_HANDLE      WrapperHandle;

UNICODE_STRING nameString, linkString;
UINT FuncIndex;
PDEVICE_OBJECT MyDeviceObject;
PDRIVER_DISPATCH MajorFunction;
Status = NDIS_STATUS_SUCCESS;

//申请自旋锁 以到达资源共享的同步访问
NdisAllocateSpinLock(&GlobalLock);
//调用NdisMInitializeWrapper函数来保存在NdisWrapperHandle返回的句柄
NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);
do
{
//调用NdisMInitializeWrapper函数来保存在WrapperHandle返回的句柄
    NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
//对于MiniportCharacteristics组件,如果驱动程序不用导出MiniportXxx这样的函数,则必须赋值为NULL。
//如果要导出任何新版本的V4.0或V5.0的MiniportXxx函数,那么中间层驱动程序的主版本必须是V4.0,并且提供4.0或5.0版本的MiniportCharacteristics组件.
NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;
   /***************************************************
      下面开始注册中间层驱动程序的 MiniportXxx函数                  
    ***************************************************/
MChars.HaltHandler             =   MPHalt;
MChars.InitializeHandler       =   MPInitialize;
MChars.QueryInformationHandler =   MPQueryInformation;
MChars.SetInformationHandler   =   MPSetInformation;
MChars.ResetHandler            =   MPReset;
MChars.SendHandler             =   NULL;
MChars.SendPacketsHandler      =   MPSendPackets;
MChars.TransferDataHandler   =   MPTransferData;
MChars.ReturnPacketHandler   =   MPReturnPacket;
MChars.CheckForHangHandler   =   NULL;
#ifdef NDIS51_MINIPORT
MChars.CancelSendPacketsHandler =MPCancelSendPackets;
MChars.PnPEventNotifyHandler    =MPDevicePnPEvent;
MChars.AdapterShutdownHandler   =MPAdapterShutdown;
#endif // NDIS51_MINIPORT

/*
传递上一步保存的句柄,并调用NdisIMRegisterLayeredMiniport函数来注册驱动程序的MiniportXxx系列函数。其中句柄NdisWrapperHandle是由先前的NdisMInitializeWrapper函数返回的。
当驱动程序调用NdisIMInitializeDeviceInstance函数,请求中间层驱动程序的MiniportInitialize函数对虚拟NIC进行初始化时,需要把句柄NdisWrapperHandle传入NDIS
当中间层驱动程序成功地绑定到一个或者多个NIC驱动程序上的时候, 或者是绑定到一个非NIC驱动程序上的时候也会调用NdisIMInitializeDeviceInstance函数。这样做使得中间层驱动程序可以初始化Miniport组件来接受虚拟NIC上的I/O请求
*/
         Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle, &MChars, sizeof(MChars), &DriverHandle);
            if (Status != NDIS_STATUS_SUCCESS)
       {
       break;
             }
#ifndef WIN9X
NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
#endif
   
//中间层驱动程序要做的事情:
//初始化NDIS_PROTOCOL_CHARACTERISTICS类型的结构.NDIS不再支持3.0版本的协议驱动.
//能够使用4.0或5.0版本的ProtocolCharacteristic结构体,协议驱动必须支持PNP即插即用功能.
NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
NdisInitUnicodeString(&Name, L"Passthru");
PChars.Name = Name;
/*******************************************************         
          下面开始注册中间层驱动程序的ProtocolXxx函数                  
    这里主要是注册---下边界面向无连接的中间层驱动程序的ProtocolXxx函数   
      *******************************************************/
PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
PChars.SendCompleteHandler = PtSendComplete;
PChars.TransferDataCompleteHandler = PtTransferDataComplete;

PChars.ResetCompleteHandler = PtResetComplete;
PChars.RequestCompleteHandler = PtRequestComplete;
PChars.ReceiveHandler = PtReceive;
PChars.ReceivePacketHandler = PtReceivePacket;
PChars.ReceiveCompleteHandler = PtReceiveComplete;
PChars.StatusHandler = PtStatus;
PChars.StatusCompleteHandler = PtStatusComplete;
PChars.BindAdapterHandler = PtBindAdapter;
PChars.UnbindAdapterHandler = PtUnbindAdapter;
PChars.UnloadHandler = PtUnloadProtocol;

PChars.PnPEventHandler= PtPNPHandler;

/*
如果驱动程序随后要绑定到底层的NDIS驱动程序上,则调用NdisRegisterProtocol函数来注册驱动程序的ProtocolXxx函数。
全局变量ProtHandle是在NDIS协议驱动里面的NdisRegisterProtocol函数里面初始化的,然后中间层驱动必须保存protHandle的值,并在将来NDIS中间层驱动程序的协议部分的函数调用中作为输入参数来传递.
*/
NdisRegisterProtocol(&Status,&ProtHandle,&PChars,
       sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (Status != NDIS_STATUS_SUCCESS)
{
    NdisIMDeregisterLayeredMiniport(DriverHandle);
                  break;
}
//如果驱动程序导出了MiniportXxx和ProtocolXxx这一些列的函数,那么就调用NdisIMAssociateMiniport函数向NDIS通告有关驱动程序的微端口低边界和协议高边界信息
    NdisIMAssociateMiniport(DriverHandle, ProtHandle);
}
while (FALSE);
//----------------- 创建设备对象与符号连接----------------------------
RtlInitUnicodeString(&nameString, L"\\Device\\MyPassthru" );
RtlInitUnicodeString(&linkString, L"\\??\\MyPassthru");
for(FuncIndex = 0;
                  FuncIndex 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, ("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, ("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, ("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, ("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, ("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, ("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, ("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);
      *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, ("FilterOidRequestComplete, Request %p.\n", Request));
    Context = (PFILTER_REQUEST_CONTEXT)(&Request->SourceReserved);
    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, ("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, ("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, ("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, ("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, ("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, ("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, ("
页: [1]
查看完整版本: NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别