Wie zuverlässig und schnell die MAC-Adresse einer Netzwerkkarte, die angesichts Ihrer Geräte-Instanz-ID

Gegeben Gerät Instanz-ID für eine Netzwerk-Karte, ich würde gerne wissen, Ihre MAC-Adresse. Beispiel Gerät Instanz-ID, die auf meinem system für die integrierte Intel-Gigabit-Karte:

PCI\VEN_8086&DEV_10CC&SUBSYS_00008086&REV_00\3&33FD14CA&0&C8

So weit, der Algorithmus, den ich verwendet haben, funktioniert wie folgt:

  1. Nennen SetupDiGetClassDevs mit DIGCF_DEVICEINTERFACE.
  2. Nennen SetupDiEnumDeviceInfo um das zurückgegebene Gerät in eine SP_DEVINFO_DATA.
  3. Nennen SetupDiEnumDeviceInterfaces mit GUID_NDIS_LAN_CLASS um eine device-Schnittstelle.
  4. Nennen SetupDiGetDeviceInterfaceDetail für diese zurückgegebenen Geräte-Schnittstelle. Dies bringt uns dem Geräte-Pfad als string: \\?\pci#ven_8086&dev_10cc&subsys_00008086&rev_00#3&33fd14ca&0&c8#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{28fd5409-15bd-4c06-b62f-004d3a06f852}
  5. An dieser Stelle haben wir eine Adresse der Netzwerk-Karte-Treiber-Schnittstelle. Öffnen Sie es mit CreateFile über das Ergebnis aus #4.
  6. Nennen DeviceIoControl mit IOCTL_NDIS_QUERY_GLOBAL_STATS und OID OID_802_3_PERMANENT_ADDRESS, um die MAC-Adresse.

Dies funktioniert in der Regel, und ist erfolgreich verwendet worden, die auf eine Recht große Anzahl von Maschinen. Es scheint jedoch, dass ganz wenige Maschinen haben den Netzwerk-Treibern, die nicht richtig reagiert, um die DeviceIoControl Anfrage in Schritt #6; das problem auch nach der Aktualisierung der Netzwerk-Karte-Treiber auf die neueste. Diese sind höher, Windows 7-basierten Computern. Insbesondere DeviceIoControl erfolgreich ausgeführt, aber es gibt null, bytes statt der erwarteten sechs Byte enthalten die MAC-Adresse.

Einen Anhaltspunkt zu sein scheint, auf der MSDN-Seite für IOCTL_NDIS_QUERY_GLOBAL_STATS:

Diese IOCTL wird deprecated in späteren Betriebssystem-Versionen. Sie
sollte mit WMI-Schnittstellen zum Abfragen miniport-Treiber Informationen. Für
mehr Informationen finden Sie unter NDIS-Unterstützung für WMI.

-- vielleicht neuere Treiber der Netzwerkkarten sind nicht mehr die Umsetzung dieser IOCTL?

So, wie soll ich damit es funktioniert? Ist es möglich, es ist ein versehen in mein Ansatz und ich mache etwas falsch? Oder muss ich eine ganz andere Herangehensweise? Einige Alternative Ansätze scheinen zu gehören:

  • Abfrage Win32_NetworkAdapter WMI-Klasse: stellt die benötigten Informationen aber abgelehnt, weil zu schrecklich Leistung. Sehen Schnellen Ersatz für WMI-Klasse Win32_NetworkAdapter für die erste MAC-Adresse des lokalen Computers
  • Abfrage MSNdis_EthernetPermanentAddress WMI-Klasse: erscheint, werden die WMI-Ersatz für IOCTL_NDIS_QUERY_GLOBAL_STATS und fragt die OID auch direkt von der Treiber - und dieses funktioniert auf die lästigen Netzwerk-Treiber. Leider werden die zurückgegebenen Instanzen der Klasse nur die MAC-Adresse und die InstanceName, das ist eine lokalisierte Zeichenfolge, wie Intel(R) 82567LM-2 Gigabit Network Connection. Abfragen MSNdis_EnumerateAdapter ergibt eine Liste, die sich die InstanceName zu einem DeviceName wie \DEVICE\{28FD5409-15BD-4C06-B62F-004D3A06F852}. Ich bin mir nicht sicher, wie man aus der DeviceName nach dem plug-and-play-Gerät Instanz-ID (PCI\VEN_8086......).
  • Nennen GetAdaptersAddresses oder GetAdaptersInfo (veraltet). Die einzige nicht-lokalisierte Bezeichner, die ich finden kann, ist der Rückgabewert der adapter-Namen, einen string, der wie {28FD5409-15BD-4C06-B62F-004D3A06F852} - wie die DeviceName zurückgegeben, die mit der WMI-NDIS-Klassen. Also nochmal, ich kann nicht herausfinden, wie Sie beziehen sich auf die Geräte-Instanz-ID. Ich bin mir nicht sicher, ob es funktioniert 100% der Zeit, die entweder - z.B. für Adapter, ohne die TCP/IP-Protokoll konfiguriert werden.
  • NetBIOS-Methode: erfordert spezielle Protokolle eingerichtet werden, die auf der Karte so nicht funktioniert 100% der Zeit. Generell scheint hack-ish, und nicht ein Weg, eine Beziehung zu den Geräte-Instanz-ID, die jedenfalls, die ich kenne. Ich würde dies ablehnen Ansatz.
  • Generierung der UUID-Methode: abgelehnt aus Gründen, die ich nicht näher erläutern hier.

Es scheint, dass, wenn ich könnte einen Weg finden, um die "GUID" für die Karte aus dem Gerät Instanz-ID, ich würde mich gut auf meinem Weg mit einem von den beiden verbleibenden Möglichkeiten, Dinge zu tun. Aber ich habe nicht herausgefunden, wie noch. Ansonsten, die WMI-NDIS-Ansatz scheint am meisten Erfolg Versprechen.

Immer eine Liste von Netzwerkkarten und MAC-Adressen ist leicht, und es gibt mehrere Möglichkeiten, es zu tun. Tue es in eine schnelle Art und Weise, die mir erlaubt, Sie beziehen sich auf die Geräte-Instanz-ID ist offenbar schwer...

EDIT: Beispielcode der IOCTL-Aufruf, wenn es hilft jemand (ignorieren Sie die geleckt handle hFile):

HANDLE hFile = CreateFile(dosDevice.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
    DWORD err = GetLastError();
    wcout << "GetMACAddress: CreateFile on " << dosDevice << " failed." << endl;
    return MACAddress();
}
BYTE address[6];
DWORD oid = OID_802_3_PERMANENT_ADDRESS, returned = 0;
//this fails too: DWORD oid = OID_802_3_CURRENT_ADDRESS, returned = 0;
if (!DeviceIoControl(hFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), address, 6, &returned, NULL)) {
    DWORD err = GetLastError();
    wcout << "GetMACAddress: DeviceIoControl on " << dosDevice << " failed." << endl;
    return MACAddress();
}
if (returned != 6) {
    wcout << "GetMACAddress: invalid address length of " << returned << "." << endl;
    return MACAddress();
}

Der code schlägt fehl, Druck:

GetMACAddress: invalid address length of 0.

Also die DeviceIoControl gibt nicht-null Erfolg, aber wieder null bytes.

Schreibe einen Kommentar