WEB开发网
开发学院操作系统windows 2008 深度剖析WinPcap之(七)——获得与释放网络适配器设... 阅读

深度剖析WinPcap之(七)——获得与释放网络适配器设备列表(3)

 2009-09-11 00:00:00 来源:WEB开发网   
核心提示:1.4.2.3 PacketAddAdapterNPF函数函数PacketAddAdapterNPF()向适配器链表g_AdaptersInfoList中添加一个节点,参数AdName是要添加的链表节点的适配器名称,深度剖析WinPcap之(七)——获得与释放网络适配器设备列表(3),如果函数成功则返回非0值,其主要代

1.4.2.3     PacketAddAdapterNPF函数

函数PacketAddAdapterNPF()向适配器链表g_AdaptersInfoList中添加一个节点。参数AdName是要添加的链表节点的适配器名称。如果函数成功则返回非0值。

其主要代码如下所示:

static BOOLEAN PacketAddAdapterNPF(PCHAR AdName, UINT flags)
{
    LONG        Status;
    LPADAPTER   adapter = NULL;
    PPACKET_OID_DATA  OidData = NULL;
    PADAPTER_INFO   TmpAdInfo;
    PADAPTER_INFO TAdInfo;
  
    /*
    *检查ADAPTER_INFO::Name成员是否有足够的空间存储适配器名称
*如果没有,函数返回失败
*/
    if (strlen(AdName) + 1 > sizeof(TmpAdInfo->Name))
    {
        return FALSE;
    }
 
/*获得g_AdaptersInfoMutex互斥信号*/
    WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
  
/*查看适配器的名称是否已在适配器链表中,如是,则函数返回*/
    for(TAdInfo = g_AdaptersInfoList; TAdInfo != NULL;
TAdInfo = TAdInfo->Next)
    {
        if(strcmp(AdName, TAdInfo->Name) == 0)
        {// AdName已存在链表中,函数返回
            ReleaseMutex(g_AdaptersInfoMutex);
            return TRUE;
        }
    }
  
    //此处不能释放g_AdaptersInfoMutex互斥信号
//如此时有两个线程试图添加同一个适配器,链表中将存在一个适配器的副本
  
    if(flags != INFO_FLAG_DONT_EXPORT)
    {   //试图打开NPF适配器,查看它是否可用
      
        //试图打开适配器
        adapter = PacketOpenAdapterNPF(AdName);
      
        if(adapter != NULL)
        {
            //分配一个缓冲区,从驱动程序获得厂商的描述 
            OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,512);
            if (OidData == NULL)
            {   //分配失败    
                PacketCloseAdapter(adapter);
                ReleaseMutex(g_AdaptersInfoMutex);
                TRACE_EXIT("PacketAddAdapterNPF");
                return FALSE;
            }
        }
        else
        {
//NPF适配器不可用,不添加到链表中       
            ReleaseMutex(g_AdaptersInfoMutex);
            TRACE_EXIT("AddAdapter");
            return FALSE;
        }         
    }
 
    /*
*获得该适配器的PADAPTER_INFO结构体中各成员的值
*/
 
    // PacketOpenAdapter成功,认为这是一个可用的适配器,
//为它在适配器链表中分配一个条目。
    TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));
    if (TmpAdInfo == NULL)
    {//内存分配失败,函数返回
        …
    }
  
    // 复制适配器名称AdName到TmpAdInfo->Name中
    strncpy(TmpAdInfo->Name, AdName,
sizeof(TmpAdInfo->Name)/ sizeof(TmpAdInfo->Name[0]) - 1);
    //无需给TmpAdInfo->Name添加结束符,
//既然在尾部预留了一个字节,同时分配TmpAdInfo内存时已设为0。
 
    if(flags != INFO_FLAG_DONT_EXPORT)
    {
        PNPF_IF_ADDRESS_ITEM pAddressesFromRegistry;
 
        //对NIC驱动的查询,获得适配器的描述
OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
        OidData->Length = 256;
        ZeroMemory(OidData->Data, 256);
      
        Status = PacketRequest(adapter, FALSE, OidData);
      
        if(Status==0 || ((char*)OidData->Data)[0]==0)
        {
//不能从NIC驱动程序获得适配器的描述信息       
        }
              
        //复制设备的描述
        strncpy(TmpAdInfo->Description, (PCHAR)OidData->Data,
 sizeof(TmpAdInfo->Description)/ sizeof(TmpAdInfo->Description[0]) - 1);
       //无需给TmpAdInfo->Name添加结束符,既然在尾部预留了一个
//字节,同时分配TmpAdInfo内存时已设为0。
 
//从注册表获得一个适配器的NetType结构体,
//该结构体包含适配器的链接类型与速度
        Status = PacketGetLinkLayerFromRegistry(adapter, &(TmpAdInfo->LinkLayer));
        if (Status == FALSE)
        {//失败,函数返回
            …
        }
      
        //查询NIC驱动程序,获取适配器的MAC地址
// 现在只支持以太网,等待补丁程序支持其它的链路层.
        OidData->Oid = OID_802_3_CURRENT_ADDRESS; 
        OidData->Length = 256;
        ZeroMemory(OidData->Data, 256);
      
        Status = PacketRequest(adapter, FALSE, OidData);
        if(Status)
        {//成功获取MAC地址,地址长度设为6
            memcpy(TmpAdInfo->MacAddress, OidData->Data, 6);
            TmpAdInfo->MacAddressLen = 6;         
        }
        else
        {//获取MAC地址失败,设为00:00:00:00:00:00,长度设为0。
            memset(TmpAdInfo->MacAddress, 0, 6);
            TmpAdInfo->MacAddressLen = 0;
        }     
      
       //获取网络地址项PNPF_IF_ADDRESS_ITEM
        TmpAdInfo->pNetworkAddresses = NULL;
        //从注册表中获取一个适配器的网络地址项
        if(!PacketGetAddressesFromRegistry(TmpAdInfo->Name,
            &pAddressesFromRegistry))
        {
        }
        else
        {
            PNPF_IF_ADDRESS_ITEM pCursor;
 
            //把pAddressesFromRegistry追加到链表
//TmpAdInfo->pNetworkAddresses的尾部
            if (TmpAdInfo->pNetworkAddresses == NULL)
            {
                TmpAdInfo->pNetworkAddresses =
                    pAddressesFromRegistry;
            }
            else
            {
                pCursor = TmpAdInfo->pNetworkAddresses;
                while(pCursor->Next != NULL)
pCursor = pCursor->Next;
 
                pCursor->Next = pAddressesFromRegistry;
            }
        }
      
        TmpAdInfo->Flags = INFO_FLAG_NDIS_ADAPTER;
// NdisWan适配器不会被NPF驱动程序导出,
//因此此处不可能见到它们
      
        //释放内存
        PacketCloseAdapter(adapter);
        GlobalFreePtr(OidData);
    }
    else
    {
        //是火线适配器,设置该标识,使后续调用将阻止它
        TmpAdInfo->Flags = INFO_FLAG_DONT_EXPORT;
    }
  
    /*更新g_AdaptersInfoList 链表*/
    TmpAdInfo->Next = g_AdaptersInfoList;
    g_AdaptersInfoList = TmpAdInfo;
 
/*释放g_AdaptersInfoMutex互斥信号*/
    ReleaseMutex(g_AdaptersInfoMutex);
 
    return TRUE;
}

1 2 3 4 5 6  下一页

Tags:深度 剖析 WinPcap

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接