Search
Categories
Articles
Rainmeter関連
ファイル置き場
お知り合いなど

スポンサーサイト

--.--.-- | スポンサー広告

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Rainmeter-dev] ネットワークトラフィックの値がおかしい #3

2010.01.29 | Rainmeter-dev // Issue/ネットワーク関連

0 Comments

前回の記事 : [Rainmeter-dev] ネットワークトラフィックの値がおかしい #2

前回の記事では、ネットワークトラフィック値が本来の値の数倍になってしまう原因について調べました。
その中ではまとめとしてフィルタインタフェース(とループバック)を除外する対象としましたが、それだけだとXPの結果とは違い、論理インタフェースも集計対象になってしまうので、ここではXPでの列挙内容に近づけるために、物理(ハードウェア)インタフェースのみを集計対象とします。
(その他のインタフェースも、Interface=0での集計対象とならないだけで、個別指定をすれば値を取得できる)

Vista以降の環境で上記のような判定をするためには、GetIfTable2(GetIfTable2Ex) APIを使います。そのまま使うと2000/XPでRainmeterが起動できなくなるので、LoadLibrary/GetProcAddress APIを使って動的に使う必要があります。コード詳細は後回しにして、GetIfTable2Ex APIを使って取得した結果は以下のようになりました。

* NETWORK-INTERFACE: Count=32

1: AMD PCNET Family Ethernet Adapter (PCI) - VirtualBox Bridged Networking Driver Miniport
  Type=Other(1), Hardware=No, Filter=No
2: Intel(R) PRO/1000 MT Desktop Adapter - VirtualBox Bridged Networking Driver Miniport
  Type=Other(1), Hardware=No, Filter=No
3: WAN Miniport (IPv6)
  Type=Ethernet(6), Hardware=No, Filter=No
4: WAN Miniport (Network Monitor)
  Type=Ethernet(6), Hardware=No, Filter=No
5: AMD PCNET Family Ethernet Adapter (PCI) #2-agnitum firewall driver-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
6: AMD PCNET Family Ethernet Adapter (PCI) #2 - VirtualBox Bridged Networking Driver Miniport
  Type=Ethernet(6), Hardware=No, Filter=Yes
7: WAN Miniport (IP)
  Type=Ethernet(6), Hardware=No, Filter=No
8: AMD PCNET Family Ethernet Adapter (PCI) #2 - VirtualBox Bridged Networking Driver Miniport-QoS Packet Scheduler-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
9: Intel(R) PRO/1000 MT Desktop Adapter
  Type=Ethernet(6), Hardware=Yes, Filter=No
10: AMD PCNET Family Ethernet Adapter (PCI)
  Type=Ethernet(6), Hardware=No, Filter=No
11: AMD PCNET Family Ethernet Adapter (PCI) #2
  Type=Ethernet(6), Hardware=Yes, Filter=No
12: WAN Miniport (IPv6)-agnitum firewall driver-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
13: WAN Miniport (IPv6)-QoS Packet Scheduler-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
14: WAN Miniport (IP)-agnitum firewall driver-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
15: WAN Miniport (IP)-QoS Packet Scheduler-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
16: WAN Miniport (Network Monitor)-agnitum firewall driver-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
17: WAN Miniport (Network Monitor)-QoS Packet Scheduler-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
18: AMD PCNET Family Ethernet Adapter (PCI) #2 - VirtualBox Bridged Networking Driver Miniport-WFP LightWeight Filter-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
19: VirtualBox Host-Only Ethernet Adapter
  Type=Ethernet(6), Hardware=Yes, Filter=No
20: VirtualBox Host-Only Ethernet Adapter-agnitum firewall driver-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
21: VirtualBox Host-Only Ethernet Adapter-QoS Packet Scheduler-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
22: VirtualBox Host-Only Ethernet Adapter-WFP LightWeight Filter-0000
  Type=Ethernet(6), Hardware=No, Filter=Yes
23: WAN Miniport (PPPOE)
  Type=PPP(23), Hardware=No, Filter=No
24: RAS Async Adapter
  Type=PPP(23), Hardware=No, Filter=No
25: Software Loopback Interface 1
  Type=Loopback(24), Hardware=No, Filter=No
26: WAN Miniport (SSTP)
  Type=Tunnel(131), Hardware=No, Filter=No
27: WAN Miniport (IKEv2)
  Type=Tunnel(131), Hardware=No, Filter=No
28: WAN Miniport (L2TP)
  Type=Tunnel(131), Hardware=No, Filter=No
29: WAN Miniport (PPTP)
  Type=Tunnel(131), Hardware=No, Filter=No
30: Microsoft ISATAP Adapter
  Type=Tunnel(131), Hardware=No, Filter=No
31: Microsoft Teredo Tunneling Adapter
  Type=Tunnel(131), Hardware=No, Filter=No
32: Microsoft ISATAP Adapter #2
  Type=Tunnel(131), Hardware=No, Filter=No

太字にしたものがハードウェアインタフェースです。9番は既に取り外されているインタフェースで(状態を出力するとIfOperStatusNotPresentが返る)、11番は実際にネットワークにつながって通信可能なインタフェース、19番はVirtualBoxが作成したインタフェースです。
(10番も本来はHardware=Yesのはずですが、VMwareで何度も設定を変えて認識させているうちに#2ができたりして状態がおかしくなったのか、Noになっています。9番同様、取り外されているという認識になっているので、集計上は問題はなさそう)

この環境ではInterface=0で上記3つのインタフェースの合計値を出すことになりますが、9番は使われていないので0、19番はゲストOS側でこのインタフェースを使わない限りは0(?)と思われるので、実質11番のみの値が出力されることになります。問題となっていたフィルタインタフェースも集計されません。

※ "Hardware=No, Filter=No"な論理インタフェースについては不明な部分もあり、どうチェックしたらいいのかもわからないので、今回は足しこまないようにしてあります(論理インタフェースということは、結局は物理インタフェースのどれかを使って通信をしているのではとも考えられるので)。また、携帯電話デバイスが認識される環境もあるようですが、どういう風に認識しているのか謎です。

続きからはコード詳細。

まずは新APIを使うための下準備から。
必要な構造体などの定義のほか、トラフィック値を保持するためのメンバ変数の32→64ビット化も必要になります。

#include "Measure.h"
#include <Iphlpapi.h>
 
//
// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/ OID_GEN_MEDIA_IN_USE).
//
typedef enum _NDIS_MEDIUM
{
    NdisMedium802_3,
    NdisMedium802_5,
    NdisMediumFddi,
    NdisMediumWan,
    NdisMediumLocalTalk,
    NdisMediumDix,              // defined for convenience, not a real medium
    NdisMediumArcnetRaw,
    NdisMediumArcnet878_2,
    NdisMediumAtm,
    NdisMediumWirelessWan,
    NdisMediumIrda,
    NdisMediumBpc,
    NdisMediumCoWan,
    NdisMedium1394,
    NdisMediumInfiniBand,
#if ((NTDDI_VERSION >= NTDDI_LONGHORN) || NDIS_SUPPORT_NDIS6)
    NdisMediumTunnel,
    NdisMediumNative802_11,
    NdisMediumLoopback,
#endif // (NTDDI_VERSION >= NTDDI_LONGHORN)
    NdisMediumMax               // Not a real medium, defined as an upper-bound
} NDIS_MEDIUM, *PNDIS_MEDIUM;
 
//
// Physical Medium Type definitions. Used with OID_GEN_PHYSICAL_MEDIUM.
//
typedef enum _NDIS_PHYSICAL_MEDIUM
{
    NdisPhysicalMediumUnspecified,
    NdisPhysicalMediumWirelessLan,
    NdisPhysicalMediumCableModem,
    NdisPhysicalMediumPhoneLine,
    NdisPhysicalMediumPowerLine,
    NdisPhysicalMediumDSL,      // includes ADSL and UADSL (G.Lite)
    NdisPhysicalMediumFibreChannel,
    NdisPhysicalMedium1394,
    NdisPhysicalMediumWirelessWan,
    NdisPhysicalMediumNative802_11,
    NdisPhysicalMediumBluetooth,
    NdisPhysicalMediumInfiniband,
    NdisPhysicalMediumWiMax,
    NdisPhysicalMediumUWB,
    NdisPhysicalMedium802_3,
    NdisPhysicalMedium802_5,
    NdisPhysicalMediumIrda,
    NdisPhysicalMediumWiredWAN,
    NdisPhysicalMediumWiredCoWan,
    NdisPhysicalMediumOther,
    NdisPhysicalMediumMax       // Not a real physical type, defined as an upper-bound
} NDIS_PHYSICAL_MEDIUM, *PNDIS_PHYSICAL_MEDIUM;
 
typedef struct _MIB_IF_ROW2 {
    //
    // Key structure.  Sorted by preference.
    //
    NET_LUID InterfaceLuid;
    NET_IFINDEX InterfaceIndex; 
 
    //
    // Read-Only fields.
    //
    GUID InterfaceGuid;
    WCHAR Alias[IF_MAX_STRING_SIZE + 1]; 
    WCHAR Description[IF_MAX_STRING_SIZE + 1];
    ULONG PhysicalAddressLength;
    UCHAR PhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH];
    UCHAR PermanentPhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH];    
 
    ULONG Mtu;
    IFTYPE Type;                // Interface Type.
    TUNNEL_TYPE TunnelType;     // Tunnel Type, if Type = IF_TUNNEL.
    NDIS_MEDIUM MediaType; 
    NDIS_PHYSICAL_MEDIUM PhysicalMediumType; 
    NET_IF_ACCESS_TYPE AccessType;
    NET_IF_DIRECTION_TYPE DirectionType;
    struct {
        BOOLEAN HardwareInterface : 1;
        BOOLEAN FilterInterface : 1;
        BOOLEAN ConnectorPresent : 1;
        BOOLEAN NotAuthenticated : 1;
        BOOLEAN NotMediaConnected : 1;
        BOOLEAN Paused : 1;
        BOOLEAN LowPower : 1;
        BOOLEAN EndPointInterface : 1;
    } InterfaceAndOperStatusFlags;
    
    IF_OPER_STATUS OperStatus;  
    NET_IF_ADMIN_STATUS AdminStatus;
    NET_IF_MEDIA_CONNECT_STATE MediaConnectState;
    NET_IF_NETWORK_GUID NetworkGuid;
    NET_IF_CONNECTION_TYPE ConnectionType; 
 
    //
    // Statistics.
    //
    ULONG64 TransmitLinkSpeed;
    ULONG64 ReceiveLinkSpeed;
 
    ULONG64 InOctets;
    ULONG64 InUcastPkts;
    ULONG64 InNUcastPkts;
    ULONG64 InDiscards;
    ULONG64 InErrors;
    ULONG64 InUnknownProtos;
    ULONG64 InUcastOctets;      
    ULONG64 InMulticastOctets;  
    ULONG64 InBroadcastOctets; 
    ULONG64 OutOctets;
    ULONG64 OutUcastPkts;
    ULONG64 OutNUcastPkts;
    ULONG64 OutDiscards;
    ULONG64 OutErrors;
    ULONG64 OutUcastOctets;     
    ULONG64 OutMulticastOctets; 
    ULONG64 OutBroadcastOctets;   
    ULONG64 OutQLen; 
} MIB_IF_ROW2, *PMIB_IF_ROW2;
 
typedef struct _MIB_IF_TABLE2 {
    ULONG NumEntries;
    MIB_IF_ROW2 Table[ANY_SIZE];
} MIB_IF_TABLE2, *PMIB_IF_TABLE2;
 
typedef enum _MIB_IF_TABLE_LEVEL {
    MibIfTableNormal,
    MibIfTableRaw
} MIB_IF_TABLE_LEVEL, *PMIB_IF_TABLE_LEVEL;
 
typedef NETIO_STATUS (NETIOAPI_API_ * FPGETIFTABLE2EX)(MIB_IF_TABLE_LEVEL Level, PMIB_IF_TABLE2* Table);
typedef VOID (NETIOAPI_API_ * FPFREEMIBTABLE)(PVOID Memory);
 
class CMeasureNet : public CMeasure
{
public:
    /* ... */
 
    static void InitializeNewApi();
    static void FinalizeNewApi();
 
protected:
    /* ... */
 
    ULONG64 GetNetOctets(NET net);
    ULONG64 GetNetStatsValue(NET net);
 
    /* ... */
 
    static std::vector<ULONG64> c_OldStatValues;
    static std::vector<ULONG64> c_StatValues;
    static BYTE* c_Table;
    static UINT c_NumOfTables;
 
    static HINSTANCE c_IpHlpApiLibrary;
    static FPGETIFTABLE2EX c_GetIfTable2Ex;
    static FPFREEMIBTABLE c_FreeMibTable;
    static bool c_UseNewApi;
};

新APIを使うにはInitializeNewApi関数を呼び出して初期化し、使い終わったらFinalizeNewApi関数を呼び出して後始末をするようにします。InitializeNewApi関数を呼び出すタイミングはRainmeter起動時に1回(CRainmeter::Initialize関数で)、FinalizeNewApi関数はRainmeter終了時に1回(CRainmeterのデストラクタで)とします。

/*
** InitializeNewApi
**
** Prepares in order to use the new APIs which are available on Vista or higher.
**
*/
void CMeasureNet::InitializeNewApi()
{
    if (c_IpHlpApiLibrary == NULL)
    {
        c_IpHlpApiLibrary = LoadLibrary(L"IpHlpApi.dll");
        if (c_IpHlpApiLibrary)
        {
            c_GetIfTable2Ex = (FPGETIFTABLE2EX)GetProcAddress(c_IpHlpApiLibrary, "GetIfTable2Ex");
            c_FreeMibTable = (FPFREEMIBTABLE)GetProcAddress(c_IpHlpApiLibrary, "FreeMibTable");
        }
 
        c_UseNewApi = (c_IpHlpApiLibrary && c_GetIfTable2Ex && c_FreeMibTable);
 
        if (!c_UseNewApi)
        {
            if (c_IpHlpApiLibrary)
            {
                FreeLibrary(c_IpHlpApiLibrary);
                c_IpHlpApiLibrary = NULL;
            }
            c_GetIfTable2Ex = NULL;
            c_FreeMibTable = NULL;
        }
    }
}
 
/*
** FinalizeNewApi
**
** Frees the resources.
**
*/
void CMeasureNet::FinalizeNewApi()
{
    if (c_UseNewApi)
    {
        c_FreeMibTable(c_Table);
 
        FreeLibrary(c_IpHlpApiLibrary);
        c_IpHlpApiLibrary = NULL;
        c_GetIfTable2Ex = NULL;
        c_FreeMibTable = NULL;
    }
    else
    {
        delete [] c_Table;
    }
    c_Table = NULL;
    c_NumOfTables = 0;
 
    c_UseNewApi = false;
}

InitializeNewApi関数では、GetIfTable2Ex APIのほか、FreeMibTable APIのアドレスも取得しています。GetIfTable2(Ex) APIは今までのGetIfTable APIとは違い、呼び出し元でバッファを作って渡すのではなく、GetIfTable2(Ex) API側でバッファを確保して情報を返してくれます。その領域が不要になったときに呼ぶのがFreeMibTable APIです。
新APIのアドレスが正常に取得できたら、フラグ(c_UseNewApi)を立てておきます。このフラグが立っていたら新APIを使い、立っていなければ今までどおりのAPIを使います。Vista以降では新API、Vista以前の2000/XPでは旧APIが使われるはずです。

FinalizeNewApi関数では、読み込んだDLLの解放やバッファの削除などを行います。

次に、これらのAPIを使ってトラフィック値を取得しているUpdateIfTable関数を修正します。
この関数はCMeterWindow::Update関数から、各Measure(NetIn/Out/Total)の値を更新する前に呼ばれます。新旧APIどちらを使うかによって処理が違うので若干長いです。

/*
** UpdateIFTable
**
** Reads the tables for all net interfaces
**
*/
void CMeasureNet::UpdateIFTable()
{
    bool logging = false;
 
    if (c_UseNewApi)
    {
        if (c_Table)
        {
            c_FreeMibTable(c_Table);
            c_Table = NULL;
        }
 
        if (c_GetIfTable2Ex(MibIfTableRaw, (MIB_IF_TABLE2**)&c_Table) == NO_ERROR)
        {
            MIB_IF_TABLE2* ifTable = (MIB_IF_TABLE2*)c_Table;
 
            if (c_NumOfTables != ifTable->NumEntries)
            {
                c_NumOfTables = ifTable->NumEntries;
                logging = true;
            }
 
            if (CRainmeter::GetVerboseLogging() && logging)
            {
                DebugLog(L"------------------------------");
                DebugLog(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables);
 
                for (size_t i = 0; i < c_NumOfTables; i++)
                {
                    std::wstring type;
                    switch (ifTable->Table[i].Type)
                    {
                    case IF_TYPE_ETHERNET_CSMACD:
                        type += L"Ethernet";
                        break;
                    case IF_TYPE_PPP:
                        type += L"PPP";
                        break;
                    case IF_TYPE_SOFTWARE_LOOPBACK:
                        type += L"Loopback";
                        break;
                    case IF_TYPE_IEEE80211:
                        type += L"IEEE802.11";
                        break;
                    case IF_TYPE_TUNNEL:
                        type += L"Tunnel";
                        break;
                    case IF_TYPE_IEEE1394:
                        type += L"IEEE1394";
                        break;
                    default:
                        type += L"Other";
                        break;
                    }
 
                    DebugLog(L"%i: %s", i + 1, ifTable->Table[i].Description);
                    DebugLog(L"  Type=%s(%i), Hardware=%s, Filter=%s",
                        type.c_str(), ifTable->Table[i].Type,
                        (ifTable->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 1) ? L"Yes" : L"No",
                        (ifTable->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) ? L"Yes" : L"No");
                }
                DebugLog(L"------------------------------");
            }
        }
        else
        {
            // Something's wrong. Unable to get the table.
            c_Table = NULL;
            c_NumOfTables = 0;
        }
    }
    else
    {
        if (c_Table == NULL)
        {
            // Gotta reserve few bytes for the tables
            DWORD value = 0;
            if (GetNumberOfInterfaces(&value) == NO_ERROR)
            {
                if (c_NumOfTables != value)
                {
                    c_NumOfTables = value;
                    logging = true;
                }
 
                if (c_NumOfTables > 0)
                {
                    DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables;
                    c_Table = new BYTE[size];
                }
            }
        }
 
        if (c_Table)
        {
            DWORD ret, size = 0;
 
            MIB_IFTABLE* ifTable = (MIB_IFTABLE*)c_Table;
 
            if ((ret = GetIfTable(ifTable, &size, FALSE)) == ERROR_INSUFFICIENT_BUFFER)
            {
                delete [] c_Table;
                c_Table = new BYTE[size];
 
                ifTable = (MIB_IFTABLE*)c_Table;
 
                ret = GetIfTable(ifTable, &size, FALSE);
            }
 
            if (ret == NO_ERROR)
            {
                if (c_NumOfTables != ifTable->dwNumEntries)
                {
                    c_NumOfTables = ifTable->dwNumEntries;
                    logging = true;
                }
 
                if (CRainmeter::GetVerboseLogging() && logging)
                {
                    DebugLog(L"------------------------------");
                    DebugLog(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables);
 
                    for (size_t i = 0; i < c_NumOfTables; i++)
                    {
                        std::string desc((char*)ifTable->table[i].bDescr, ifTable->table[i].dwDescrLen);
 
                        std::wstring type;
                        switch (ifTable->table[i].dwType)
                        {
                        case IF_TYPE_ETHERNET_CSMACD:
                            type += L"Ethernet";
                            break;
                        case IF_TYPE_PPP:
                            type += L"PPP";
                            break;
                        case IF_TYPE_SOFTWARE_LOOPBACK:
                            type += L"Loopback";
                            break;
                        case IF_TYPE_IEEE80211:
                            type += L"IEEE802.11";
                            break;
                        case IF_TYPE_TUNNEL:
                            type += L"Tunnel";
                            break;
                        case IF_TYPE_IEEE1394:
                            type += L"IEEE1394";
                            break;
                        default:
                            type += L"Other";
                            break;
                        }
 
                        DebugLog(L"%i: %s", i + 1, ConvertToWide(desc.c_str()).c_str());
                        DebugLog(L"  Type=%s(%i)",
                            type.c_str(), ifTable->table[i].dwType);
                    }
                    DebugLog(L"------------------------------");
                }
            }
            else
            {
                // Something's wrong. Unable to get the table.
                delete [] c_Table;
                c_Table = NULL;
                c_NumOfTables = 0;
            }
        }
    }
}

処理内容自体は今までと大きく変わりません。値を受け取るバッファを用意する必要があるかどうかと、受け取った構造体メンバの扱い方がちょっと違う程度です。

次に、Measure値が更新される際に呼ばれるGetNetOctets関数、GetNetStatsValue関数を修正します。

/*
** GetNetOctets
**
** Reads the amount of octets. This is the same for in, out and total.
** the net-parameter informs which inherited class called this method.
**
*/
ULONG64 CMeasureNet::GetNetOctets(NET net)
{
    ULONG64 value = 0;
 
    if (c_UseNewApi)
    {
        MIB_IF_ROW2* table = (MIB_IF_ROW2*)((MIB_IF_TABLE2*)c_Table)->Table;
 
        if (m_Interface == 0)
        {
            // Get all interfaces
            for (UINT i = 0; i < c_NumOfTables; i++)
            {
                // Ignore the loopback and non-hardware interfaces
                if (table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK ||
                    table[i].InterfaceAndOperStatusFlags.HardwareInterface == 0) continue;
 
                switch (net)
                {
                case NET_IN:
                    value += table[i].InOctets;
                    break;
 
                case NET_OUT:
                    value += table[i].OutOctets;
                    break;
 
                case NET_TOTAL:
                    value += table[i].InOctets;
                    value += table[i].OutOctets;
                    break;
                }
            }
        }
        else
        {
            // Get the selected interface
            if (m_Interface <= c_NumOfTables)
            {
                switch (net)
                {
                case NET_IN:
                    value += table[m_Interface - 1].InOctets;
                    break;
 
                case NET_OUT:
                    value += table[m_Interface - 1].OutOctets;
                    break;
 
                case NET_TOTAL:
                    value += table[m_Interface - 1].InOctets;
                    value += table[m_Interface - 1].OutOctets;
                    break;
                }
            }
        }
    }
    else
    {
        MIB_IFROW* table = (MIB_IFROW*)((MIB_IFTABLE*)c_Table)->table;
 
        if (m_Interface == 0)
        {
            // Get all interfaces
            for (UINT i = 0; i < c_NumOfTables; i++)
            {
                // Ignore the loopback
                if (table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
 
                switch (net)
                {
                case NET_IN:
                    value += table[i].dwInOctets;
                    break;
 
                case NET_OUT:
                    value += table[i].dwOutOctets;
                    break;
 
                case NET_TOTAL:
                    value += table[i].dwInOctets;
                    value += table[i].dwOutOctets;
                    break;
                }
            }
        }
        else
        {
            // Get the selected interface
            if (m_Interface <= c_NumOfTables)
            {
                switch (net)
                {
                case NET_IN:
                    value += table[m_Interface - 1].dwInOctets;
                    break;
 
                case NET_OUT:
                    value += table[m_Interface - 1].dwOutOctets;
                    break;
 
                case NET_TOTAL:
                    value += table[m_Interface - 1].dwInOctets;
                    value += table[m_Interface - 1].dwOutOctets;
                    break;
                }
            }
        }
    }
 
    return value;
}
 
/*
** GetNetStatsValue
**
** Returns the stats value of the interface
**
*/
ULONG64 CMeasureNet::GetNetStatsValue(NET net)
{
    ULONG64 value = 0;
 
    if (m_Interface == 0)
    {
        // Get all interfaces
        for(size_t i = 0; i < c_StatValues.size() / 2; i++)
        {
            // Ignore the loopback and non-hardware interfaces
            if (c_NumOfTables == c_StatValues.size() / 2)
            {
                if (c_UseNewApi)
                {
                    if (((MIB_IF_TABLE2*)c_Table)->Table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK ||
                        ((MIB_IF_TABLE2*)c_Table)->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 0) continue;
                }
                else
                {
                    if (((MIB_IFTABLE*)c_Table)->table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
                }
            }
 
            switch (net)
            {
            case NET_IN:
                value += c_StatValues[i * 2 + 0];
                break;
 
            case NET_OUT:
                value += c_StatValues[i * 2 + 1];
                break;
 
            case NET_TOTAL:
                value += c_StatValues[i * 2 + 0];
                value += c_StatValues[i * 2 + 1];
                break;
            }
        }
    }
    else
    {
        // Get the selected interface
        if (m_Interface <= c_StatValues.size() / 2)
        {
            switch (net)
            {
            case NET_IN:
                value += c_StatValues[(m_Interface - 1) * 2 + 0];
                break;
 
            case NET_OUT:
                value += c_StatValues[(m_Interface - 1) * 2 + 1];
                break;
 
            case NET_TOTAL:
                value += c_StatValues[(m_Interface - 1) * 2 + 0];
                value += c_StatValues[(m_Interface - 1) * 2 + 1];
                break;
            }
        }
    }
 
    return value;
}

旧APIを使う場合の集計除外対象も、今までは

            // Ignore the loopback
            if(strcmp((char*)c_Table->table[i].bDescr, "MS TCP Loopback interface") != 0)

……のようにインタフェース名決めうちでループバックインタフェースを除外していましたが、インタフェースの種類を表すフラグをチェックして、ループバックであれば除外するように変更しています。新APIを使う場合にはこれに加え、ハードウェアインタフェースを表すフラグが立っていないものも除外対象にしています。

その他、集計部分の処理には大きな変更はありません。今まで32ビットDWORD値で集計していたものを、新APIに合わせるために64ビットULONG64値で集計するように変更してあるくらいです。これらの関数以外でも同様の変更が必要となりますが、説明は省略します(NetIn/Out/Total側も同様)。

« [Rainmeter] スキンファイル(iniファイル)をUnicodeで記述する [Rainmeter-dev] ネットワークトラフィックの値がおかしい #2 »

- Comments
0 Comments

管理者にだけ表示を許可する
- Trackbacks
0 Trackbacks


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。