2019-01-31 14:20:11 +00:00
/ * SPDX - License - Identifier : MIT
*
* Copyright ( C ) 2019 WireGuard LLC . All Rights Reserved .
* /
package setupapi
import (
2019-02-05 10:44:47 +00:00
"encoding/binary"
"fmt"
2019-05-03 07:34:00 +00:00
"runtime"
2019-02-01 09:58:06 +00:00
"syscall"
2019-02-01 10:39:57 +00:00
"unsafe"
2019-02-01 09:58:06 +00:00
2019-01-31 14:20:11 +00:00
"golang.org/x/sys/windows"
2019-02-01 12:00:44 +00:00
"golang.org/x/sys/windows/registry"
2019-01-31 14:20:11 +00:00
)
2019-02-07 02:24:58 +00:00
//sys setupDiCreateDeviceInfoListEx(classGUID *windows.GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(windows.InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW
2019-02-04 07:23:55 +00:00
2019-02-04 14:21:19 +00:00
// SetupDiCreateDeviceInfoListEx function creates an empty device information set on a remote or a local computer and optionally associates the set with a device setup class.
2019-02-07 02:24:58 +00:00
func SetupDiCreateDeviceInfoListEx ( classGUID * windows . GUID , hwndParent uintptr , machineName string ) ( deviceInfoSet DevInfo , err error ) {
2019-02-04 08:51:19 +00:00
var machineNameUTF16 * uint16
2019-02-07 02:24:58 +00:00
if machineName != "" {
machineNameUTF16 , err = syscall . UTF16PtrFromString ( machineName )
2019-02-04 07:39:31 +00:00
if err != nil {
return
}
}
2019-02-07 02:24:58 +00:00
return setupDiCreateDeviceInfoListEx ( classGUID , hwndParent , machineNameUTF16 , 0 )
2019-02-04 14:21:19 +00:00
}
2019-02-04 07:39:31 +00:00
2019-02-07 21:23:03 +00:00
//sys setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW
2019-02-04 07:23:55 +00:00
2019-02-04 14:21:19 +00:00
// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
2019-02-07 02:24:58 +00:00
func SetupDiGetDeviceInfoListDetail ( deviceInfoSet DevInfo ) ( deviceInfoSetDetailData * DevInfoListDetailData , err error ) {
2019-02-07 21:23:03 +00:00
data := & DevInfoListDetailData { }
2019-04-19 08:05:04 +00:00
data . size = sizeofDevInfoListDetailData
2019-02-04 07:23:55 +00:00
2019-02-07 21:23:03 +00:00
return data , setupDiGetDeviceInfoListDetail ( deviceInfoSet , data )
2019-02-04 08:36:42 +00:00
}
2019-05-22 17:31:52 +00:00
// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
func ( deviceInfoSet DevInfo ) DeviceInfoListDetail ( ) ( * DevInfoListDetailData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetDeviceInfoListDetail ( deviceInfoSet )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:09:18 +00:00
//sys setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *windows.GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW
2019-02-04 14:21:19 +00:00
2019-02-04 10:52:42 +00:00
// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set.
2019-02-07 21:09:18 +00:00
func SetupDiCreateDeviceInfo ( deviceInfoSet DevInfo , deviceName string , classGUID * windows . GUID , deviceDescription string , hwndParent uintptr , creationFlags DICD ) ( deviceInfoData * DevInfoData , err error ) {
2019-02-07 02:24:58 +00:00
deviceNameUTF16 , err := syscall . UTF16PtrFromString ( deviceName )
2019-02-04 10:52:42 +00:00
if err != nil {
return
}
var deviceDescriptionUTF16 * uint16
2019-02-07 02:24:58 +00:00
if deviceDescription != "" {
deviceDescriptionUTF16 , err = syscall . UTF16PtrFromString ( deviceDescription )
2019-02-04 10:52:42 +00:00
if err != nil {
return
}
}
2019-02-07 21:09:18 +00:00
data := & DevInfoData { }
data . size = uint32 ( unsafe . Sizeof ( * data ) )
2019-02-04 10:52:42 +00:00
2019-02-07 21:09:18 +00:00
return data , setupDiCreateDeviceInfo ( deviceInfoSet , deviceNameUTF16 , classGUID , deviceDescriptionUTF16 , hwndParent , creationFlags , data )
2019-02-04 10:52:42 +00:00
}
2019-02-05 07:45:44 +00:00
// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) CreateDeviceInfo ( deviceName string , classGUID * windows . GUID , deviceDescription string , hwndParent uintptr , creationFlags DICD ) ( * DevInfoData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiCreateDeviceInfo ( deviceInfoSet , deviceName , classGUID , deviceDescription , hwndParent , creationFlags )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:09:18 +00:00
//sys setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo
2019-02-04 14:21:19 +00:00
2019-02-07 21:09:18 +00:00
// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set.
func SetupDiEnumDeviceInfo ( deviceInfoSet DevInfo , memberIndex int ) ( * DevInfoData , error ) {
data := & DevInfoData { }
data . size = uint32 ( unsafe . Sizeof ( * data ) )
2019-02-04 14:21:19 +00:00
2019-02-07 21:09:18 +00:00
return data , setupDiEnumDeviceInfo ( deviceInfoSet , uint32 ( memberIndex ) , data )
2019-02-04 10:49:26 +00:00
}
2019-02-07 21:09:18 +00:00
// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set.
func ( deviceInfoSet DevInfo ) EnumDeviceInfo ( memberIndex int ) ( * DevInfoData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiEnumDeviceInfo ( deviceInfoSet , memberIndex )
2019-02-05 07:45:44 +00:00
}
2019-02-04 14:21:19 +00:00
// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.
2019-02-07 02:24:58 +00:00
//sys SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList
2019-02-04 14:21:19 +00:00
2019-02-05 07:45:44 +00:00
// Close method deletes a device information set and frees all associated memory.
2019-02-07 02:24:58 +00:00
func ( deviceInfoSet DevInfo ) Close ( ) error {
return SetupDiDestroyDeviceInfoList ( deviceInfoSet )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:09:18 +00:00
//sys SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList
2019-02-05 15:29:17 +00:00
// BuildDriverInfoList method builds a list of drivers that is associated with a specific device or with the global class driver list for a device information set.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) BuildDriverInfoList ( deviceInfoData * DevInfoData , driverType SPDIT ) error {
2019-02-07 02:24:58 +00:00
return SetupDiBuildDriverInfoList ( deviceInfoSet , deviceInfoData , driverType )
2019-02-05 15:29:17 +00:00
}
2019-02-07 02:24:58 +00:00
//sys SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch
2019-02-05 15:29:17 +00:00
// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread.
2019-02-07 02:24:58 +00:00
func ( deviceInfoSet DevInfo ) CancelDriverInfoSearch ( ) error {
return SetupDiCancelDriverInfoSearch ( deviceInfoSet )
2019-02-05 15:29:17 +00:00
}
2019-02-07 22:12:58 +00:00
//sys setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW
2019-02-05 15:29:17 +00:00
// SetupDiEnumDriverInfo function enumerates the members of a driver list.
2019-02-07 22:12:58 +00:00
func SetupDiEnumDriverInfo ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData , driverType SPDIT , memberIndex int ) ( * DrvInfoData , error ) {
data := & DrvInfoData { }
data . size = uint32 ( unsafe . Sizeof ( * data ) )
2019-02-05 15:29:17 +00:00
2019-02-07 02:24:58 +00:00
return data , setupDiEnumDriverInfo ( deviceInfoSet , deviceInfoData , driverType , uint32 ( memberIndex ) , data )
2019-02-05 15:29:17 +00:00
}
// EnumDriverInfo method enumerates the members of a driver list.
2019-02-07 22:12:58 +00:00
func ( deviceInfoSet DevInfo ) EnumDriverInfo ( deviceInfoData * DevInfoData , driverType SPDIT , memberIndex int ) ( * DrvInfoData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiEnumDriverInfo ( deviceInfoSet , deviceInfoData , driverType , memberIndex )
2019-02-05 15:29:17 +00:00
}
2019-02-07 22:12:58 +00:00
//sys setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW
2019-02-05 15:29:17 +00:00
// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element.
2019-02-07 22:12:58 +00:00
func SetupDiGetSelectedDriver ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData ) ( * DrvInfoData , error ) {
data := & DrvInfoData { }
data . size = uint32 ( unsafe . Sizeof ( * data ) )
2019-02-05 15:29:17 +00:00
2019-02-07 02:24:58 +00:00
return data , setupDiGetSelectedDriver ( deviceInfoSet , deviceInfoData , data )
2019-02-05 15:29:17 +00:00
}
2019-05-22 17:31:52 +00:00
// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element.
func ( deviceInfoSet DevInfo ) SelectedDriver ( deviceInfoData * DevInfoData ) ( * DrvInfoData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetSelectedDriver ( deviceInfoSet , deviceInfoData )
2019-02-05 15:29:17 +00:00
}
2019-02-07 22:12:58 +00:00
//sys SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW
2019-02-05 15:29:17 +00:00
// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.
2019-02-07 22:12:58 +00:00
func ( deviceInfoSet DevInfo ) SetSelectedDriver ( deviceInfoData * DevInfoData , driverInfoData * DrvInfoData ) error {
2019-02-07 02:24:58 +00:00
return SetupDiSetSelectedDriver ( deviceInfoSet , deviceInfoData , driverInfoData )
2019-02-05 15:29:17 +00:00
}
2019-02-07 22:45:11 +00:00
//sys setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW
2019-02-05 15:29:17 +00:00
// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.
2019-02-07 22:45:11 +00:00
func SetupDiGetDriverInfoDetail ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData , driverInfoData * DrvInfoData ) ( * DrvInfoDetailData , error ) {
2019-02-05 15:29:17 +00:00
const bufCapacity = 0x800
buf := [ bufCapacity ] byte { }
var bufLen uint32
2019-02-07 22:45:11 +00:00
data := ( * DrvInfoDetailData ) ( unsafe . Pointer ( & buf [ 0 ] ) )
2019-04-19 08:05:04 +00:00
data . size = sizeofDrvInfoDetailData
2019-02-05 15:29:17 +00:00
2019-02-07 22:45:11 +00:00
err := setupDiGetDriverInfoDetail ( deviceInfoSet , deviceInfoData , driverInfoData , data , bufCapacity , & bufLen )
2019-02-05 15:29:17 +00:00
if err == nil {
// The buffer was was sufficiently big.
2019-02-07 22:45:11 +00:00
data . size = bufLen
return data , nil
2019-02-05 15:29:17 +00:00
}
if errWin , ok := err . ( syscall . 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 )
2019-02-07 22:45:11 +00:00
data := ( * DrvInfoDetailData ) ( unsafe . Pointer ( & buf [ 0 ] ) )
2019-04-19 08:05:04 +00:00
data . size = sizeofDrvInfoDetailData
2019-02-05 15:29:17 +00:00
2019-02-07 22:45:11 +00:00
err = setupDiGetDriverInfoDetail ( deviceInfoSet , deviceInfoData , driverInfoData , data , bufLen , & bufLen )
2019-02-05 15:29:17 +00:00
if err == nil {
2019-02-07 22:45:11 +00:00
data . size = bufLen
return data , nil
2019-02-05 15:29:17 +00:00
}
}
2019-02-07 22:45:11 +00:00
return nil , err
2019-02-05 15:29:17 +00:00
}
2019-05-22 17:31:52 +00:00
// 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 ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetDriverInfoDetail ( deviceInfoSet , deviceInfoData , driverInfoData )
2019-02-05 15:29:17 +00:00
}
2019-02-07 21:09:18 +00:00
//sys SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList
2019-02-05 15:29:17 +00:00
// DestroyDriverInfoList method deletes a driver list.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) DestroyDriverInfoList ( deviceInfoData * DevInfoData , driverType SPDIT ) error {
2019-02-07 02:24:58 +00:00
return SetupDiDestroyDriverInfoList ( deviceInfoSet , deviceInfoData , driverType )
2019-02-05 15:29:17 +00:00
}
2019-02-07 02:24:58 +00:00
//sys setupDiGetClassDevsEx(classGUID *windows.GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(windows.InvalidHandle)] = setupapi.SetupDiGetClassDevsExW
2019-02-04 14:21:19 +00:00
2019-02-01 10:39:57 +00:00
// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer.
2019-02-07 02:24:58 +00:00
func SetupDiGetClassDevsEx ( classGUID * windows . GUID , enumerator string , hwndParent uintptr , flags DIGCF , deviceInfoSet DevInfo , machineName string ) ( handle DevInfo , err error ) {
2019-02-04 08:51:19 +00:00
var enumeratorUTF16 * uint16
2019-02-07 02:24:58 +00:00
if enumerator != "" {
enumeratorUTF16 , err = syscall . UTF16PtrFromString ( enumerator )
2019-02-01 09:58:06 +00:00
if err != nil {
return
}
}
2019-02-04 08:51:19 +00:00
var machineNameUTF16 * uint16
2019-02-07 02:24:58 +00:00
if machineName != "" {
machineNameUTF16 , err = syscall . UTF16PtrFromString ( machineName )
2019-02-01 09:58:06 +00:00
if err != nil {
return
}
}
2019-02-07 02:24:58 +00:00
return setupDiGetClassDevsEx ( classGUID , enumeratorUTF16 , hwndParent , flags , deviceInfoSet , machineNameUTF16 , 0 )
2019-02-01 10:39:57 +00:00
}
2019-02-04 14:21:19 +00:00
// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
2019-02-07 21:09:18 +00:00
//sys SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller
2019-02-04 10:40:44 +00:00
2019-02-05 07:45:44 +00:00
// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) CallClassInstaller ( installFunction DI_FUNCTION , deviceInfoData * DevInfoData ) error {
2019-02-07 02:24:58 +00:00
return SetupDiCallClassInstaller ( installFunction , deviceInfoSet , deviceInfoData )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:09:18 +00:00
//sys setupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key windows.Handle, err error) [failretval==windows.InvalidHandle] = setupapi.SetupDiOpenDevRegKey
2019-02-01 11:17:09 +00:00
2019-02-01 12:00:44 +00:00
// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.
2019-02-07 21:09:18 +00:00
func SetupDiOpenDevRegKey ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData , scope DICS_FLAG , hwProfile uint32 , keyType DIREG , samDesired uint32 ) ( registry . Key , error ) {
2019-02-07 02:24:58 +00:00
handle , err := setupDiOpenDevRegKey ( deviceInfoSet , deviceInfoData , scope , hwProfile , keyType , samDesired )
2019-02-01 12:00:44 +00:00
return registry . Key ( handle ) , err
2019-02-01 11:17:09 +00:00
}
2019-02-01 12:59:53 +00:00
2019-02-05 07:45:44 +00:00
// OpenDevRegKey method opens a registry key for device-specific configuration information.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) OpenDevRegKey ( DeviceInfoData * DevInfoData , Scope DICS_FLAG , HwProfile uint32 , KeyType DIREG , samDesired uint32 ) ( registry . Key , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiOpenDevRegKey ( deviceInfoSet , DeviceInfoData , Scope , HwProfile , KeyType , samDesired )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:09:18 +00:00
//sys setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW
2019-02-05 10:44:47 +00:00
// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property.
2019-02-07 21:09:18 +00:00
func SetupDiGetDeviceRegistryProperty ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData , property SPDRP ) ( value interface { } , err error ) {
2019-02-05 10:44:47 +00:00
buf := make ( [ ] byte , 0x100 )
var dataType , bufLen uint32
2019-02-07 02:24:58 +00:00
err = setupDiGetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property , & dataType , & buf [ 0 ] , uint32 ( cap ( buf ) ) , & bufLen )
2019-02-05 10:44:47 +00:00
if err == nil {
// The buffer was sufficiently big.
return getRegistryValue ( buf [ : bufLen ] , dataType )
}
if errWin , ok := err . ( syscall . 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 )
2019-02-07 02:24:58 +00:00
err = setupDiGetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property , & dataType , & buf [ 0 ] , uint32 ( cap ( buf ) ) , & bufLen )
2019-02-05 10:44:47 +00:00
if err == nil {
return getRegistryValue ( buf [ : bufLen ] , dataType )
}
}
return
}
func getRegistryValue ( buf [ ] byte , dataType uint32 ) ( interface { } , error ) {
switch dataType {
case windows . REG_SZ :
2019-05-03 07:34:00 +00:00
ret := windows . UTF16ToString ( bufToUTF16 ( buf ) )
runtime . KeepAlive ( buf )
return ret , nil
2019-02-05 10:44:47 +00:00
case windows . REG_EXPAND_SZ :
2019-05-03 07:34:00 +00:00
ret , err := registry . ExpandString ( windows . UTF16ToString ( bufToUTF16 ( buf ) ) )
runtime . KeepAlive ( buf )
return ret , err
2019-02-05 10:44:47 +00:00
case windows . REG_BINARY :
return buf , nil
case windows . REG_DWORD_LITTLE_ENDIAN :
return binary . LittleEndian . Uint32 ( buf ) , nil
case windows . REG_DWORD_BIG_ENDIAN :
return binary . BigEndian . Uint32 ( buf ) , nil
case windows . REG_MULTI_SZ :
2019-05-03 07:34:00 +00:00
bufW := bufToUTF16 ( buf )
2019-02-05 10:44:47 +00:00
a := [ ] string { }
for i := 0 ; i < len ( bufW ) ; {
j := i + wcslen ( bufW [ i : ] )
if i < j {
a = append ( a , windows . UTF16ToString ( bufW [ i : j ] ) )
}
i = j + 1
}
2019-05-03 07:34:00 +00:00
runtime . KeepAlive ( buf )
2019-02-05 10:44:47 +00:00
return a , nil
case windows . REG_QWORD_LITTLE_ENDIAN :
return binary . LittleEndian . Uint64 ( buf ) , nil
default :
return nil , fmt . Errorf ( "Unsupported registry value type: %v" , dataType )
}
}
2019-05-03 07:34:00 +00:00
// bufToUTF16 function reinterprets []byte buffer as []uint16
func bufToUTF16 ( buf [ ] byte ) [ ] uint16 {
2019-02-05 10:44:47 +00:00
sl := struct {
addr * uint16
len int
cap int
} { ( * uint16 ) ( unsafe . Pointer ( & buf [ 0 ] ) ) , len ( buf ) / 2 , cap ( buf ) / 2 }
return * ( * [ ] uint16 ) ( unsafe . Pointer ( & sl ) )
}
2019-05-03 07:34:00 +00:00
// utf16ToBuf function reinterprets []uint16 as []byte
func utf16ToBuf ( buf [ ] uint16 ) [ ] byte {
2019-02-06 19:15:40 +00:00
sl := struct {
addr * byte
len int
cap int
} { ( * byte ) ( unsafe . Pointer ( & buf [ 0 ] ) ) , len ( buf ) * 2 , cap ( buf ) * 2 }
return * ( * [ ] byte ) ( unsafe . Pointer ( & sl ) )
}
2019-02-05 10:44:47 +00:00
func wcslen ( str [ ] uint16 ) int {
for i := 0 ; i < len ( str ) ; i ++ {
if str [ i ] == 0 {
return i
}
}
return len ( str )
}
2019-05-22 17:31:52 +00:00
// DeviceRegistryProperty method retrieves a specified Plug and Play device property.
func ( deviceInfoSet DevInfo ) DeviceRegistryProperty ( deviceInfoData * DevInfoData , property SPDRP ) ( interface { } , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property )
2019-02-05 10:44:47 +00:00
}
2019-02-07 21:09:18 +00:00
//sys setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW
2019-02-05 10:44:47 +00:00
// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device.
2019-02-07 21:09:18 +00:00
func SetupDiSetDeviceRegistryProperty ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData , property SPDRP , propertyBuffers [ ] byte ) error {
2019-02-07 02:24:58 +00:00
return setupDiSetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property , & propertyBuffers [ 0 ] , uint32 ( len ( propertyBuffers ) ) )
2019-02-05 10:44:47 +00:00
}
// SetDeviceRegistryProperty function sets a Plug and Play device property for a device.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) SetDeviceRegistryProperty ( deviceInfoData * DevInfoData , property SPDRP , propertyBuffers [ ] byte ) error {
2019-02-07 02:24:58 +00:00
return SetupDiSetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property , propertyBuffers )
2019-02-05 10:44:47 +00:00
}
2019-05-03 07:34:00 +00:00
func ( deviceInfoSet DevInfo ) SetDeviceRegistryPropertyString ( deviceInfoData * DevInfoData , property SPDRP , str string ) error {
str16 , err := windows . UTF16FromString ( str )
if err != nil {
return err
}
err = SetupDiSetDeviceRegistryProperty ( deviceInfoSet , deviceInfoData , property , utf16ToBuf ( append ( str16 , 0 ) ) )
runtime . KeepAlive ( str16 )
return err
}
2019-02-07 21:35:03 +00:00
//sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
2019-02-04 14:21:19 +00:00
2019-02-01 12:59:53 +00:00
// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
2019-02-07 21:35:03 +00:00
func SetupDiGetDeviceInstallParams ( deviceInfoSet DevInfo , deviceInfoData * DevInfoData ) ( * DevInstallParams , error ) {
params := & DevInstallParams { }
params . size = uint32 ( unsafe . Sizeof ( * params ) )
2019-02-01 12:59:53 +00:00
2019-02-07 21:35:03 +00:00
return params , setupDiGetDeviceInstallParams ( deviceInfoSet , deviceInfoData , params )
2019-02-01 12:59:53 +00:00
}
2019-05-22 17:31:52 +00:00
// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element.
func ( deviceInfoSet DevInfo ) DeviceInstallParams ( deviceInfoData * DevInfoData ) ( * DevInstallParams , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetDeviceInstallParams ( deviceInfoSet , deviceInfoData )
2019-02-05 07:45:44 +00:00
}
2019-02-04 14:21:19 +00:00
// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element.
2019-02-07 21:37:14 +00:00
//sys SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW
2019-02-04 14:21:19 +00:00
2019-05-22 17:31:52 +00:00
// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element.
func ( deviceInfoSet DevInfo ) ClassInstallParams ( deviceInfoData * DevInfoData , classInstallParams * ClassInstallHeader , classInstallParamsSize uint32 , requiredSize * uint32 ) error {
2019-02-07 02:24:58 +00:00
return SetupDiGetClassInstallParams ( deviceInfoSet , deviceInfoData , classInstallParams , classInstallParamsSize , requiredSize )
2019-02-05 07:45:44 +00:00
}
2019-02-07 21:35:03 +00:00
//sys SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW
2019-02-04 14:21:19 +00:00
2019-02-05 07:45:44 +00:00
// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) SetDeviceInstallParams ( deviceInfoData * DevInfoData , deviceInstallParams * DevInstallParams ) error {
2019-02-07 02:24:58 +00:00
return SetupDiSetDeviceInstallParams ( deviceInfoSet , deviceInfoData , deviceInstallParams )
2019-02-05 07:45:44 +00:00
}
2019-02-04 14:21:19 +00:00
// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element.
2019-02-07 21:37:14 +00:00
//sys SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW
2019-02-04 14:21:19 +00:00
2019-02-05 07:45:44 +00:00
// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element.
2019-02-07 21:37:14 +00:00
func ( deviceInfoSet DevInfo ) SetClassInstallParams ( deviceInfoData * DevInfoData , classInstallParams * ClassInstallHeader , classInstallParamsSize uint32 ) error {
2019-02-07 02:24:58 +00:00
return SetupDiSetClassInstallParams ( deviceInfoSet , deviceInfoData , classInstallParams , classInstallParamsSize )
2019-02-05 07:45:44 +00:00
}
2019-02-07 02:24:58 +00:00
//sys setupDiClassNameFromGuidEx(classGUID *windows.GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW
2019-02-04 14:21:19 +00:00
// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer.
2019-02-07 02:24:58 +00:00
func SetupDiClassNameFromGuidEx ( classGUID * windows . GUID , machineName string ) ( className string , err error ) {
2019-02-04 14:21:19 +00:00
var classNameUTF16 [ MAX_CLASS_NAME_LEN ] uint16
var machineNameUTF16 * uint16
2019-02-07 02:24:58 +00:00
if machineName != "" {
machineNameUTF16 , err = syscall . UTF16PtrFromString ( machineName )
2019-02-04 14:21:19 +00:00
if err != nil {
return
}
}
2019-02-07 02:24:58 +00:00
err = setupDiClassNameFromGuidEx ( classGUID , & classNameUTF16 [ 0 ] , MAX_CLASS_NAME_LEN , nil , machineNameUTF16 , 0 )
2019-02-04 14:21:19 +00:00
if err != nil {
return
}
2019-02-07 02:24:58 +00:00
className = windows . UTF16ToString ( classNameUTF16 [ : ] )
2019-02-04 14:21:19 +00:00
return
}
2019-02-07 02:24:58 +00:00
//sys setupDiClassGuidsFromNameEx(className *uint16, classGuidList *windows.GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW
2019-02-04 14:21:19 +00:00
// SetupDiClassGuidsFromNameEx function retrieves the GUIDs associated with the specified class name. This resulting list contains the classes currently installed on a local or remote computer.
2019-03-04 13:27:16 +00:00
func SetupDiClassGuidsFromNameEx ( className string , machineName string ) ( [ ] windows . GUID , error ) {
2019-02-07 02:24:58 +00:00
classNameUTF16 , err := syscall . UTF16PtrFromString ( className )
2019-02-04 14:21:19 +00:00
if err != nil {
2019-03-04 13:27:16 +00:00
return nil , err
2019-02-04 14:21:19 +00:00
}
2019-02-05 10:44:47 +00:00
const bufCapacity = 4
var buf [ bufCapacity ] windows . GUID
var bufLen uint32
2019-02-04 14:21:19 +00:00
var machineNameUTF16 * uint16
2019-02-07 02:24:58 +00:00
if machineName != "" {
machineNameUTF16 , err = syscall . UTF16PtrFromString ( machineName )
2019-02-04 14:21:19 +00:00
if err != nil {
2019-03-04 13:27:16 +00:00
return nil , err
2019-02-04 14:21:19 +00:00
}
}
2019-02-05 10:44:47 +00:00
err = setupDiClassGuidsFromNameEx ( classNameUTF16 , & buf [ 0 ] , bufCapacity , & bufLen , machineNameUTF16 , 0 )
2019-02-04 14:21:19 +00:00
if err == nil {
// The GUID array was sufficiently big. Return its slice.
2019-02-05 10:44:47 +00:00
return buf [ : bufLen ] , nil
2019-02-04 14:21:19 +00:00
}
if errWin , ok := err . ( syscall . 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.
2019-02-05 10:44:47 +00:00
buf := make ( [ ] windows . GUID , bufLen )
err = setupDiClassGuidsFromNameEx ( classNameUTF16 , & buf [ 0 ] , bufLen , & bufLen , machineNameUTF16 , 0 )
2019-02-04 14:21:19 +00:00
if err == nil {
2019-02-05 10:44:47 +00:00
return buf [ : bufLen ] , nil
2019-02-04 14:21:19 +00:00
}
}
2019-03-04 13:27:16 +00:00
return nil , err
2019-02-04 14:21:19 +00:00
}
2019-02-04 14:50:59 +00:00
2019-02-07 21:09:18 +00:00
//sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice
2019-02-04 14:50:59 +00:00
// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set.
2019-02-07 21:09:18 +00:00
func SetupDiGetSelectedDevice ( deviceInfoSet DevInfo ) ( * DevInfoData , error ) {
data := & DevInfoData { }
data . size = uint32 ( unsafe . Sizeof ( * data ) )
2019-02-04 14:50:59 +00:00
2019-02-07 21:09:18 +00:00
return data , setupDiGetSelectedDevice ( deviceInfoSet , data )
2019-02-04 14:50:59 +00:00
}
2019-05-22 17:31:52 +00:00
// SelectedDevice method retrieves the selected device information element in a device information set.
func ( deviceInfoSet DevInfo ) SelectedDevice ( ) ( * DevInfoData , error ) {
2019-02-07 02:24:58 +00:00
return SetupDiGetSelectedDevice ( deviceInfoSet )
2019-02-05 07:45:44 +00:00
}
2019-02-04 14:50:59 +00:00
// SetupDiSetSelectedDevice function sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard.
2019-02-07 21:09:18 +00:00
//sys SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice
2019-02-05 07:45:44 +00:00
// SetSelectedDevice method sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard.
2019-02-07 21:09:18 +00:00
func ( deviceInfoSet DevInfo ) SetSelectedDevice ( deviceInfoData * DevInfoData ) error {
2019-02-07 02:24:58 +00:00
return SetupDiSetSelectedDevice ( deviceInfoSet , deviceInfoData )
2019-02-05 07:45:44 +00:00
}