setupapi: unify ERROR_INSUFFICIENT_BUFFER handling

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-06-10 08:47:16 +02:00 committed by Jason A. Donenfeld
parent e924280baa
commit a1a97d1e41

View File

@ -150,35 +150,22 @@ func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driv
// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set. // SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.
func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
const bufCapacity = 0x800 reqSize := uint32(2048)
buf := [bufCapacity]byte{} for {
var bufLen uint32 buf := make([]byte, reqSize)
data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0])) data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
data.size = sizeofDrvInfoDetailData data.size = sizeofDrvInfoDetailData
err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)
err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, bufCapacity, &bufLen) if err == windows.ERROR_INSUFFICIENT_BUFFER {
if err == nil { continue
// The buffer was was sufficiently big.
data.size = bufLen
return data, nil
} }
if err != nil {
if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_INSUFFICIENT_BUFFER {
// The buffer was too small. Now that we got the required size, create another one big enough and retry.
buf := make([]byte, bufLen)
data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
data.size = sizeofDrvInfoDetailData
err = setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, bufLen, &bufLen)
if err == nil {
data.size = bufLen
return data, nil
}
}
return nil, err return nil, err
} }
data.size = reqSize
return data, nil
}
}
// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set. // DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set.
func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
@ -238,25 +225,20 @@ func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DI
// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property. // SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property.
func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) { func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) {
buf := make([]byte, 0x100) reqSize := uint32(256)
var dataType, bufLen uint32 for {
err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(cap(buf)), &bufLen) var dataType uint32
if err == nil { buf := make([]byte, reqSize)
// The buffer was sufficiently big. err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)
return getRegistryValue(buf[:bufLen], dataType) if err == windows.ERROR_INSUFFICIENT_BUFFER {
continue
} }
if err != nil {
if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_INSUFFICIENT_BUFFER {
// The buffer was too small. Now that we got the required size, create another one big enough and retry.
buf = make([]byte, bufLen)
err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(cap(buf)), &bufLen)
if err == nil {
return getRegistryValue(buf[:bufLen], dataType)
}
}
return return
} }
return getRegistryValue(buf[:reqSize], dataType)
}
}
func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) { func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
switch dataType { switch dataType {
@ -442,10 +424,6 @@ func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]window
return nil, err return nil, err
} }
const bufCapacity = 4
var buf [bufCapacity]windows.GUID
var bufLen uint32
var machineNameUTF16 *uint16 var machineNameUTF16 *uint16
if machineName != "" { if machineName != "" {
machineNameUTF16, err = windows.UTF16PtrFromString(machineName) machineNameUTF16, err = windows.UTF16PtrFromString(machineName)
@ -454,23 +432,19 @@ func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]window
} }
} }
err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], bufCapacity, &bufLen, machineNameUTF16, 0) reqSize := uint32(4)
if err == nil { for {
// The GUID array was sufficiently big. Return its slice. buf := make([]windows.GUID, reqSize)
return buf[:bufLen], nil err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)
if err == windows.ERROR_INSUFFICIENT_BUFFER {
continue
} }
if err != nil {
if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_INSUFFICIENT_BUFFER {
// The GUID array was too small. Now that we got the required size, create another one big enough and retry.
buf := make([]windows.GUID, bufLen)
err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], bufLen, &bufLen, machineNameUTF16, 0)
if err == nil {
return buf[:bufLen], nil
}
}
return nil, err return nil, err
} }
return buf[:reqSize], nil
}
}
//sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice //sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice