Hi all,
I’ve been trying to use the python ctypes library (which talks to Windows DLLs directly) to make calls to SetupAPI and get a network adapter’s CompatibleIDs
(The intention is to figure out consistently whether it is a LAN adapter or a Wireless adapter. (and the code will run on Win XP+))
So, here’s what I’m doing:
- (For now manually) get the GUID of my device from the reg key HKLM\Software\Microsoft\Windows NT\CurrentVersion\NetworkCard<networkconnection status>
2) Call SetupDiGetClassGetDevsW with a GUID object and get back a Device Information Set
3) Call SetupDiEnumDeviceInterfaces with the returned handle from one, and a pointer to a SP_DEVICE_INTERFACE_DATA object.
Now, the return value from 2 comes out False, and when I call GetLastError it gives me a 259 (For No More Items I believe)
Questions:
1) Can anyone suggest why it can’t find my network card even though I give it the correct GUID?
2) Is there a simpler or more practical approach for distinguishing between a LAN and Wireless adapter? Win32_NetworkAdapter.AdapterTypeId is not consistent on the wireless cards that I’ll be querying.
Here’s the code:
import win32com.client
import socket
import winreg
import ctypes
from ctypes import *
from ctypes.wintypes import *
import sys
import re
class GUID(Structure):
fields = [(“Data1”, c_ulong),
(“Data2”, c_ushort),
(“Data3”, c_ushort),
(“Data4”, c_ubyte * 8)]
class SP_DEVICE_INTERFACE_DATA(Structure):
fields = [(‘cbSize’, DWORD),
(‘InterfaceClassGuid’, GUID),
(‘Flags’, DWORD),
(‘Reserved’, POINTER(ULONG))]
wmi_cl = win32com.client.Dispatch(‘WbemScripting.SWbemLocator’)
conn = wmi_cl.ConnectServer(socket.gethostname(), ‘root\cimv2’)
adapters = conn.ExecQuery(‘SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionID LIKE “%LOCAL%”’)
status = adapters[0].NetConnectionStatus
# Fetch the GUID from registry
raw_string = r’Software\Microsoft\Windows NT\CurrentVersion\NetworkCards%s’ % status
hkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, raw_string)
guid = winreg.EnumValue(hkey, 0)[1]
guid = re.sub(‘-’, ‘’, guid[1:-1])
print guid
#Convert the GUID string into a proper GUID object
hex_bytes = [guid_[i:i+2] for i in range(0, len(guid_),2)]
print hex_bytes
DEVICE = GUID(eval(‘0x’+‘’.join(hex_bytes[0:4])),
eval(‘0x’+hex_bytes[4]+hex_bytes[5]),
eval(‘0x’+hex_bytes[6]+hex_bytes[7]),
(eval(‘0x’+hex_bytes[8]),
eval(‘0x’+hex_bytes[9]),
eval(‘0x’+hex_bytes[10]),
eval(‘0x’+hex_bytes[11]),
eval(‘0x’+hex_bytes[12]),
eval(‘0x’+hex_bytes[13]),
eval(‘0x’+hex_bytes[14]),
eval(‘0x’+hex_bytes[15])))
print hex(DEVICE.Data1)
print hex(DEVICE.Data2)
print hex(DEVICE.Data3)
print hex(DEVICE.Data4[0])
print hex(DEVICE.Data4[1])
print hex(DEVICE.Data4[2])
print hex(DEVICE.Data4[3])
print hex(DEVICE.Data4[4])
print hex(DEVICE.Data4[5])
print hex(DEVICE.Data4[6])
print hex(DEVICE.Data4[7])
# Obtain Device Information Set for our device
hInfo = ctypes.windll.setupapi.SetupDiGetClassDevsW(byref(DEVICE), None, None, None)
if hInfo == -1:
print ‘Something went wrong’
sys.exit(0)
else:
# We could get the device information set!
# Now, get the enumerated device interfaces
in_info = SP_DEVICE_INTERFACE_DATA()
in_info.cbSize = sizeof(in_info)
found_dev = ctypes.windll.setupapi.SetupDiEnumDeviceInterfaces(hInfo, None, byref(DEVICE), 0, byref(in_info))
if not found_dev:
# We coudn’t get them :(!
print ‘Error %s occurred( If it was 259, we already have no more items. :(’ % ctypes.windll.kernel32.GetLastError()
else:
# Figure out how to get our CompatibilityID detail
# by calling SetupDiGetDeviceInterfaceDetailW and then SetupDiOpenDevRegKey
print ‘We got a device! Now code the rest!’
pass