func getNativeName(DeviceInfoSet C.HDEVINFO, DeviceInfoData C.PSP_DEVINFO_DATA) (string, error) { key := C.SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, C.DICS_FLAG_GLOBAL, 0, C.DIREG_DEV, C.KEY_READ) defer C.RegCloseKey(key) if C.is_INVALID_HANDLE_VALUE(unsafe.Pointer(key)) != C.FALSE { return "", errors.New(fmt.Sprintf("Reg error: %d", int(C.GetLastError()))) } var i C.DWORD = 0 var keyType C.DWORD = 0 buffKeyName := make([]C.CHAR, 16384) buffKeyVal := make([]C.BYTE, 16384) for { var lenKeyName C.DWORD = C.DWORD(cap(buffKeyName)) var lenKeyValue C.DWORD = C.DWORD(cap(buffKeyVal)) ret := C.RegEnumValue(key, i, &buffKeyName[0], &lenKeyName, (*C.DWORD)(nil), &keyType, &buffKeyVal[0], &lenKeyValue) i++ if ret == C.ERROR_SUCCESS { if keyType == C.REG_SZ { itemName := C.GoString((*C.char)(&buffKeyName[0])) itemValue := C.GoString((*C.char)(unsafe.Pointer((&buffKeyVal[0])))) if strings.Contains(itemName, "PortName") { return itemValue, nil } } } else { break } } return "", errors.New("Empty response") }
func enumerate() ([]DeviceDescription, error) { //log.Print("Calling windows backend") k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\services`, registry.QUERY_VALUE) if err != nil { return nil, err } defer k.Close() var result []DeviceDescription for i := 0; i < len(guidArray); i++ { DeviceInfoSet := C.SetupDiGetClassDevs(&guidArray[i], (*C.CHAR)(nil), (*C.struct_HWND__)(nil), C.DIGCF_PRESENT) if C.is_INVALID_HANDLE_VALUE(unsafe.Pointer(DeviceInfoSet)) != 0 { return nil, errors.New(fmt.Sprintf( `Windows: SerialDeviceEnumeratorPrivate::updateInfo() SetupDiGetClassDevs() returned INVALID_HANDLE_VALUE, last error: %d`, int(C.GetLastError()))) } var DeviceIndex C.DWORD = 0 var DeviceInfoData C.SP_DEVINFO_DATA DeviceInfoData.cbSize = C.DWORD(unsafe.Sizeof(DeviceInfoData)) for { if C.SetupDiEnumDeviceInfo(DeviceInfoSet, DeviceIndex, &DeviceInfoData) != C.TRUE { break } DeviceIndex++ name, err := getNativeName(DeviceInfoSet, &DeviceInfoData) if err != nil || len(name) == 0 { continue } if strings.Contains(name, "LPT") { continue } var dev DeviceDescription dev.Name = name dev.ShortName = name if dev.Bus, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_ENUMERATOR_NAME)); err != nil { log.Printf("Error get bus of device %s: %s", name, err.Error()) } if dev.Description, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_DEVICEDESC)); err != nil { log.Printf("Error get Description of device %s: %s", name, err.Error()) } if dev.FriendlyName, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_FRIENDLYNAME)); err != nil { log.Printf("Error get FriendlyName of device %s: %s", name, err.Error()) } if dev.HardwareID, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_HARDWAREID)); err != nil { log.Printf("Error get HardwareID of device %s: %s", name, err.Error()) } if dev.LocationInfo, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_LOCATION_INFORMATION)); err != nil { log.Printf("Error get LocationInfo of device %s: %s", name, err.Error()) } if dev.Manufacturer, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_MFG)); err != nil { log.Printf("Error get Manufacturer of device %s: %s", name, err.Error()) } if dev.SubSystem, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_CLASS)); err != nil { log.Printf("Error get SubSystem of device %s: %s", name, err.Error()) } if dev.Service, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_SERVICE)); err != nil { log.Printf("Error get Service of device %s: %s", name, err.Error()) } if dev.Driver, err = getNativeDriver(dev.Service); err != nil { log.Printf("Error get Driver of device %s: %s", name, err.Error()) } if dev.SystemPath, err = result2string(getDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, C.SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)); err != nil { log.Printf("Error get SystemPath of device %s: %s", name, err.Error()) } match := vidpidRegExp.FindStringSubmatch(dev.HardwareID) if len(match) > 1 { var v []byte if v, err = hex.DecodeString(match[1]); err == nil { dev.VendorID = (uint16)(v[0])<<8 + (uint16)(v[1]) } if v, err = hex.DecodeString(match[2]); err == nil { dev.ProductID = (uint16)(v[0])<<8 + (uint16)(v[1]) } } result = append(result, dev) } } return result, nil }