6         raise ctypes.WinError()
 
   10 from serial.win32 
import ULONG_PTR, is_64bit
 
   11 from ctypes.wintypes 
import HANDLE
 
   12 from ctypes.wintypes 
import BOOL
 
   13 from ctypes.wintypes 
import HWND
 
   14 from ctypes.wintypes 
import DWORD
 
   15 from ctypes.wintypes 
import WORD
 
   16 from ctypes.wintypes 
import LONG
 
   17 from ctypes.wintypes 
import ULONG
 
   18 from ctypes.wintypes 
import LPCSTR
 
   19 from ctypes.wintypes 
import HKEY
 
   20 from ctypes.wintypes 
import BYTE
 
   23 HDEVINFO = ctypes.c_void_p
 
   24 PCTSTR = ctypes.c_char_p
 
   26 LPDWORD = PDWORD = ctypes.POINTER(DWORD)
 
   28 LPBYTE = PBYTE = ctypes.c_void_p        
 
   29 PHKEY = ctypes.POINTER(HKEY)
 
   36     """Get a buffer for a string""" 
   37     return (BYTE*length)()
 
   43         s.append(chr(c & 0xff)) 
 
   47 class GUID(ctypes.Structure):
 
   55         return "{%08x-%04x-%04x-%s-%s}" % (
 
   59             ''.join([
"%02x" % d 
for d 
in self.Data4[:2]]),
 
   60             ''.join([
"%02x" % d 
for d 
in self.Data4[2:]]),
 
   68         (
'Reserved', ULONG_PTR),
 
   71         return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst)
 
   72 PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA)
 
   77         (
'InterfaceClassGuid', GUID),
 
   79         (
'Reserved', ULONG_PTR),
 
   82         return "InterfaceClassGuid:%s Flags:%s" % (self.InterfaceClassGuid, self.Flags)
 
   83 PSP_DEVICE_INTERFACE_DATA = ctypes.POINTER(SP_DEVICE_INTERFACE_DATA)
 
   85 PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p
 
   87 setupapi = ctypes.windll.LoadLibrary(
"setupapi")
 
   88 SetupDiDestroyDeviceInfoList = setupapi.SetupDiDestroyDeviceInfoList
 
   89 SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO]
 
   90 SetupDiDestroyDeviceInfoList.restype = BOOL
 
   92 SetupDiGetClassDevs = setupapi.SetupDiGetClassDevsA
 
   93 SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD]
 
   94 SetupDiGetClassDevs.restype = HDEVINFO
 
   95 SetupDiGetClassDevs.errcheck = ValidHandle
 
   97 SetupDiEnumDeviceInterfaces = setupapi.SetupDiEnumDeviceInterfaces
 
   98 SetupDiEnumDeviceInterfaces.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, ctypes.POINTER(GUID), DWORD, PSP_DEVICE_INTERFACE_DATA]
 
   99 SetupDiEnumDeviceInterfaces.restype = BOOL
 
  101 SetupDiGetDeviceInterfaceDetail = setupapi.SetupDiGetDeviceInterfaceDetailA
 
  102 SetupDiGetDeviceInterfaceDetail.argtypes = [HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA, DWORD, PDWORD, PSP_DEVINFO_DATA]
 
  103 SetupDiGetDeviceInterfaceDetail.restype = BOOL
 
  105 SetupDiGetDeviceRegistryProperty = setupapi.SetupDiGetDeviceRegistryPropertyA
 
  106 SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD]
 
  107 SetupDiGetDeviceRegistryProperty.restype = BOOL
 
  109 SetupDiOpenDevRegKey = setupapi.SetupDiOpenDevRegKey
 
  110 SetupDiOpenDevRegKey.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM]
 
  111 SetupDiOpenDevRegKey.restype = HKEY
 
  113 advapi32 = ctypes.windll.LoadLibrary(
"Advapi32")
 
  114 RegCloseKey = advapi32.RegCloseKey
 
  115 RegCloseKey.argtypes = [HKEY]
 
  116 RegCloseKey.restype = LONG
 
  118 RegQueryValueEx = advapi32.RegQueryValueExA
 
  119 RegQueryValueEx.argtypes = [HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD]
 
  120 RegQueryValueEx.restype = LONG
 
  123 GUID_CLASS_COMPORT = 
GUID(0x86e0d1e0L, 0x8089, 0x11d0,
 
  124     (BYTE*8)(0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73))
 
  127 DIGCF_DEVICEINTERFACE = 16
 
  128 INVALID_HANDLE_VALUE = 0
 
  129 ERROR_INSUFFICIENT_BUFFER = 122
 
  131 SPDRP_FRIENDLYNAME = 12
 
  132 ERROR_NO_MORE_ITEMS = 259
 
  134 DIREG_DEV = 0x00000001
 
  139 PortName = serial.to_bytes([80, 111, 114, 116, 78, 97, 109, 101]) 
 
  142     """This generator scans the device registry for com ports and yields port, desc, hwid""" 
  143     g_hdi = 
SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), 
None, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
 
  145     for dwIndex 
in range(256):
 
  147         did.cbSize = ctypes.sizeof(did)
 
  150             if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS:
 
  151                 raise ctypes.WinError()
 
  158             if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
 
  159                 raise ctypes.WinError()
 
  161         class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure):
 
  164                 (
'DevicePath', CHAR*(dwNeeded.value - ctypes.sizeof(DWORD))),
 
  167                 return "DevicePath:%s" % (self.DevicePath,)
 
  168         idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A()
 
  174         devinfo.cbSize = ctypes.sizeof(devinfo)
 
  176             raise ctypes.WinError()
 
  180         if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, 
None, ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1, 
None):
 
  182             if GetLastError() != ERROR_INSUFFICIENT_BUFFER:
 
  183                 raise ctypes.WinError()
 
  187         if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, 
None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, 
None):
 
  189             if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
 
  194             hkey = 
SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)
 
  196             port_name_length = ULONG(ctypes.sizeof(port_name_buffer))
 
  197             RegQueryValueEx(hkey, PortName, 
None, 
None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length))
 
  205 if __name__ == 
'__main__':
 
  208     for port, desc, hwid 
in sorted(
comports()):
 
  209         print "%s: %s [%s]" % (port, desc, hwid)