デバイスインスタンスパス(デバイスインスタンスID)からIPアドレスやMACアドレスなどの情報を取り出したり、あるいはその逆でデバイスインスタンスパスを得る話です。WMIを使って良ければ、Win32_NetworkAdapterのPnPDeviceIdプロパティで解決ですが、諸般の事情でこれを使いたくない場合の方法です。

Setup APIやCfgMgr APIなどで取り扱われるデバイスインスタンスパスはWindowsに接続されているデバイスを識別する文字列です。一方、ネットワーク関係のAPIでは、各ネットワークインタフェースの識別方法にGUID、LUID、インタフェースインデックスなど複数あります。これらを結び付ける方法が知りたいわけです。

これには、Network Configuration InterfacesのAPIを使います。紹介記事がBindview とINetCfg API | Japan WDK Support Blogにあります。このAPIを使うと、デバイスインスタンスパスとインタフェースGUIDの組み合わせが判明します。

以下、サンプルプログラムです。

#include <iostream>
#include <comdef.h>
#include <windows.h>
#include <netcfgx.h>
#include <devguid.h>
 
_COM_SMARTPTR_TYPEDEF(INetCfg, __uuidof(INetCfg));
_COM_SMARTPTR_TYPEDEF(INetCfgClass, __uuidof(INetCfgClass));
_COM_SMARTPTR_TYPEDEF(IEnumNetCfgComponent, __uuidof(IEnumNetCfgComponent));
_COM_SMARTPTR_TYPEDEF(INetCfgComponent, __uuidof(INetCfgComponent));
 
int main()
{
  std::locale l(std::locale::classic(), "", std::locale::ctype);
  std::wcout.imbue(l);
  std::wclog.imbue(l);
 
  HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
  if (FAILED(hr))
  {
    return static_cast<int>(hr);
  }
 
  {
    INetCfgPtr nc(CLSID_CNetCfg, nullptr, CLSCTX_INPROC_SERVER);
    nc->Initialize(nullptr);
    INetCfgClassPtr ncc;
    nc->QueryNetCfgClass(&GUID_DEVCLASS_NET, IID_PPV_ARGS(&ncc));
    IEnumNetCfgComponentPtr e;
    ncc->EnumComponents(&e);
    ULONG fetched;
    INetCfgComponentPtr component;
    while (e->Next(1, &component, &fetched) == S_OK)
    {
      DWORD characteristics;
      if (SUCCEEDED(component->GetCharacteristics(&characteristics)))
      {
        if ((characteristics & NCF_HIDDEN) != 0)
          continue;
      }
      PWSTR displayName;
      if (SUCCEEDED(component->GetDisplayName(&displayName)))
      {
        std::wcout << displayName << std::endl;
        CoTaskMemFree(displayName);
      }
      PWSTR devNodeId;
      if (SUCCEEDED(component->GetPnpDevNodeId(&devNodeId)))
      {
        std::wcout << '\t' << devNodeId << std::endl;
        CoTaskMemFree(devNodeId);
      }
      GUID guid;
      if (SUCCEEDED(component->GetInstanceGuid(&guid)))
      {
        WCHAR buf[39];
        StringFromGUID2(guid, buf, ARRAYSIZE(buf));
        std::wcout << '\t' << buf << std::endl;
      }
      std::wcout << std::hex << "\tcharacteristics: "
        << characteristics << std::endl;
    }
    nc->Uninitialize();
  }
  CoUninitialize();
}

このプログラムで出力しているGUIDは、Win32_NetworkAdapter.GUIDと一致します。

また、IP_ADAPTER_ADDRESSES::Luidとは、以下の関数で相互に変換できます。

この2関数はWindows Vistaで追加された関数です。もし、それ以前を対象とする場合はNhpAllocateAndGetInterfaceInfoFromStack関数を使いましょう。こちらでは、インタフェースインデックス (IP_ADAPTER_ADDRESSES::IfIndex)と結び付けられます。


スポンサード リンク

この記事のカテゴリ

  • ⇒ デバイスインスタンスパスからネットワークインタフェースの情報を引き出す(あるいはその逆)
  • ⇒ デバイスインスタンスパスからネットワークインタフェースの情報を引き出す(あるいはその逆)