gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

setupapi_windows.go (68854B)


      1 // Copyright 2021 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package windows
      6 
      7 import (
      8 	"encoding/binary"
      9 	"errors"
     10 	"fmt"
     11 	"runtime"
     12 	"strings"
     13 	"syscall"
     14 	"unsafe"
     15 )
     16 
     17 // This file contains functions that wrap SetupAPI.dll and CfgMgr32.dll,
     18 // core system functions for managing hardware devices, drivers, and the PnP tree.
     19 // Information about these APIs can be found at:
     20 //     https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi
     21 //     https://docs.microsoft.com/en-us/windows/win32/devinst/cfgmgr32-
     22 
     23 const (
     24 	ERROR_EXPECTED_SECTION_NAME                  Errno = 0x20000000 | 0xC0000000 | 0
     25 	ERROR_BAD_SECTION_NAME_LINE                  Errno = 0x20000000 | 0xC0000000 | 1
     26 	ERROR_SECTION_NAME_TOO_LONG                  Errno = 0x20000000 | 0xC0000000 | 2
     27 	ERROR_GENERAL_SYNTAX                         Errno = 0x20000000 | 0xC0000000 | 3
     28 	ERROR_WRONG_INF_STYLE                        Errno = 0x20000000 | 0xC0000000 | 0x100
     29 	ERROR_SECTION_NOT_FOUND                      Errno = 0x20000000 | 0xC0000000 | 0x101
     30 	ERROR_LINE_NOT_FOUND                         Errno = 0x20000000 | 0xC0000000 | 0x102
     31 	ERROR_NO_BACKUP                              Errno = 0x20000000 | 0xC0000000 | 0x103
     32 	ERROR_NO_ASSOCIATED_CLASS                    Errno = 0x20000000 | 0xC0000000 | 0x200
     33 	ERROR_CLASS_MISMATCH                         Errno = 0x20000000 | 0xC0000000 | 0x201
     34 	ERROR_DUPLICATE_FOUND                        Errno = 0x20000000 | 0xC0000000 | 0x202
     35 	ERROR_NO_DRIVER_SELECTED                     Errno = 0x20000000 | 0xC0000000 | 0x203
     36 	ERROR_KEY_DOES_NOT_EXIST                     Errno = 0x20000000 | 0xC0000000 | 0x204
     37 	ERROR_INVALID_DEVINST_NAME                   Errno = 0x20000000 | 0xC0000000 | 0x205
     38 	ERROR_INVALID_CLASS                          Errno = 0x20000000 | 0xC0000000 | 0x206
     39 	ERROR_DEVINST_ALREADY_EXISTS                 Errno = 0x20000000 | 0xC0000000 | 0x207
     40 	ERROR_DEVINFO_NOT_REGISTERED                 Errno = 0x20000000 | 0xC0000000 | 0x208
     41 	ERROR_INVALID_REG_PROPERTY                   Errno = 0x20000000 | 0xC0000000 | 0x209
     42 	ERROR_NO_INF                                 Errno = 0x20000000 | 0xC0000000 | 0x20A
     43 	ERROR_NO_SUCH_DEVINST                        Errno = 0x20000000 | 0xC0000000 | 0x20B
     44 	ERROR_CANT_LOAD_CLASS_ICON                   Errno = 0x20000000 | 0xC0000000 | 0x20C
     45 	ERROR_INVALID_CLASS_INSTALLER                Errno = 0x20000000 | 0xC0000000 | 0x20D
     46 	ERROR_DI_DO_DEFAULT                          Errno = 0x20000000 | 0xC0000000 | 0x20E
     47 	ERROR_DI_NOFILECOPY                          Errno = 0x20000000 | 0xC0000000 | 0x20F
     48 	ERROR_INVALID_HWPROFILE                      Errno = 0x20000000 | 0xC0000000 | 0x210
     49 	ERROR_NO_DEVICE_SELECTED                     Errno = 0x20000000 | 0xC0000000 | 0x211
     50 	ERROR_DEVINFO_LIST_LOCKED                    Errno = 0x20000000 | 0xC0000000 | 0x212
     51 	ERROR_DEVINFO_DATA_LOCKED                    Errno = 0x20000000 | 0xC0000000 | 0x213
     52 	ERROR_DI_BAD_PATH                            Errno = 0x20000000 | 0xC0000000 | 0x214
     53 	ERROR_NO_CLASSINSTALL_PARAMS                 Errno = 0x20000000 | 0xC0000000 | 0x215
     54 	ERROR_FILEQUEUE_LOCKED                       Errno = 0x20000000 | 0xC0000000 | 0x216
     55 	ERROR_BAD_SERVICE_INSTALLSECT                Errno = 0x20000000 | 0xC0000000 | 0x217
     56 	ERROR_NO_CLASS_DRIVER_LIST                   Errno = 0x20000000 | 0xC0000000 | 0x218
     57 	ERROR_NO_ASSOCIATED_SERVICE                  Errno = 0x20000000 | 0xC0000000 | 0x219
     58 	ERROR_NO_DEFAULT_DEVICE_INTERFACE            Errno = 0x20000000 | 0xC0000000 | 0x21A
     59 	ERROR_DEVICE_INTERFACE_ACTIVE                Errno = 0x20000000 | 0xC0000000 | 0x21B
     60 	ERROR_DEVICE_INTERFACE_REMOVED               Errno = 0x20000000 | 0xC0000000 | 0x21C
     61 	ERROR_BAD_INTERFACE_INSTALLSECT              Errno = 0x20000000 | 0xC0000000 | 0x21D
     62 	ERROR_NO_SUCH_INTERFACE_CLASS                Errno = 0x20000000 | 0xC0000000 | 0x21E
     63 	ERROR_INVALID_REFERENCE_STRING               Errno = 0x20000000 | 0xC0000000 | 0x21F
     64 	ERROR_INVALID_MACHINENAME                    Errno = 0x20000000 | 0xC0000000 | 0x220
     65 	ERROR_REMOTE_COMM_FAILURE                    Errno = 0x20000000 | 0xC0000000 | 0x221
     66 	ERROR_MACHINE_UNAVAILABLE                    Errno = 0x20000000 | 0xC0000000 | 0x222
     67 	ERROR_NO_CONFIGMGR_SERVICES                  Errno = 0x20000000 | 0xC0000000 | 0x223
     68 	ERROR_INVALID_PROPPAGE_PROVIDER              Errno = 0x20000000 | 0xC0000000 | 0x224
     69 	ERROR_NO_SUCH_DEVICE_INTERFACE               Errno = 0x20000000 | 0xC0000000 | 0x225
     70 	ERROR_DI_POSTPROCESSING_REQUIRED             Errno = 0x20000000 | 0xC0000000 | 0x226
     71 	ERROR_INVALID_COINSTALLER                    Errno = 0x20000000 | 0xC0000000 | 0x227
     72 	ERROR_NO_COMPAT_DRIVERS                      Errno = 0x20000000 | 0xC0000000 | 0x228
     73 	ERROR_NO_DEVICE_ICON                         Errno = 0x20000000 | 0xC0000000 | 0x229
     74 	ERROR_INVALID_INF_LOGCONFIG                  Errno = 0x20000000 | 0xC0000000 | 0x22A
     75 	ERROR_DI_DONT_INSTALL                        Errno = 0x20000000 | 0xC0000000 | 0x22B
     76 	ERROR_INVALID_FILTER_DRIVER                  Errno = 0x20000000 | 0xC0000000 | 0x22C
     77 	ERROR_NON_WINDOWS_NT_DRIVER                  Errno = 0x20000000 | 0xC0000000 | 0x22D
     78 	ERROR_NON_WINDOWS_DRIVER                     Errno = 0x20000000 | 0xC0000000 | 0x22E
     79 	ERROR_NO_CATALOG_FOR_OEM_INF                 Errno = 0x20000000 | 0xC0000000 | 0x22F
     80 	ERROR_DEVINSTALL_QUEUE_NONNATIVE             Errno = 0x20000000 | 0xC0000000 | 0x230
     81 	ERROR_NOT_DISABLEABLE                        Errno = 0x20000000 | 0xC0000000 | 0x231
     82 	ERROR_CANT_REMOVE_DEVINST                    Errno = 0x20000000 | 0xC0000000 | 0x232
     83 	ERROR_INVALID_TARGET                         Errno = 0x20000000 | 0xC0000000 | 0x233
     84 	ERROR_DRIVER_NONNATIVE                       Errno = 0x20000000 | 0xC0000000 | 0x234
     85 	ERROR_IN_WOW64                               Errno = 0x20000000 | 0xC0000000 | 0x235
     86 	ERROR_SET_SYSTEM_RESTORE_POINT               Errno = 0x20000000 | 0xC0000000 | 0x236
     87 	ERROR_SCE_DISABLED                           Errno = 0x20000000 | 0xC0000000 | 0x238
     88 	ERROR_UNKNOWN_EXCEPTION                      Errno = 0x20000000 | 0xC0000000 | 0x239
     89 	ERROR_PNP_REGISTRY_ERROR                     Errno = 0x20000000 | 0xC0000000 | 0x23A
     90 	ERROR_REMOTE_REQUEST_UNSUPPORTED             Errno = 0x20000000 | 0xC0000000 | 0x23B
     91 	ERROR_NOT_AN_INSTALLED_OEM_INF               Errno = 0x20000000 | 0xC0000000 | 0x23C
     92 	ERROR_INF_IN_USE_BY_DEVICES                  Errno = 0x20000000 | 0xC0000000 | 0x23D
     93 	ERROR_DI_FUNCTION_OBSOLETE                   Errno = 0x20000000 | 0xC0000000 | 0x23E
     94 	ERROR_NO_AUTHENTICODE_CATALOG                Errno = 0x20000000 | 0xC0000000 | 0x23F
     95 	ERROR_AUTHENTICODE_DISALLOWED                Errno = 0x20000000 | 0xC0000000 | 0x240
     96 	ERROR_AUTHENTICODE_TRUSTED_PUBLISHER         Errno = 0x20000000 | 0xC0000000 | 0x241
     97 	ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED     Errno = 0x20000000 | 0xC0000000 | 0x242
     98 	ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED     Errno = 0x20000000 | 0xC0000000 | 0x243
     99 	ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH         Errno = 0x20000000 | 0xC0000000 | 0x244
    100 	ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE         Errno = 0x20000000 | 0xC0000000 | 0x245
    101 	ERROR_DEVICE_INSTALLER_NOT_READY             Errno = 0x20000000 | 0xC0000000 | 0x246
    102 	ERROR_DRIVER_STORE_ADD_FAILED                Errno = 0x20000000 | 0xC0000000 | 0x247
    103 	ERROR_DEVICE_INSTALL_BLOCKED                 Errno = 0x20000000 | 0xC0000000 | 0x248
    104 	ERROR_DRIVER_INSTALL_BLOCKED                 Errno = 0x20000000 | 0xC0000000 | 0x249
    105 	ERROR_WRONG_INF_TYPE                         Errno = 0x20000000 | 0xC0000000 | 0x24A
    106 	ERROR_FILE_HASH_NOT_IN_CATALOG               Errno = 0x20000000 | 0xC0000000 | 0x24B
    107 	ERROR_DRIVER_STORE_DELETE_FAILED             Errno = 0x20000000 | 0xC0000000 | 0x24C
    108 	ERROR_UNRECOVERABLE_STACK_OVERFLOW           Errno = 0x20000000 | 0xC0000000 | 0x300
    109 	EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW
    110 	ERROR_NO_DEFAULT_INTERFACE_DEVICE            Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE
    111 	ERROR_INTERFACE_DEVICE_ACTIVE                Errno = ERROR_DEVICE_INTERFACE_ACTIVE
    112 	ERROR_INTERFACE_DEVICE_REMOVED               Errno = ERROR_DEVICE_INTERFACE_REMOVED
    113 	ERROR_NO_SUCH_INTERFACE_DEVICE               Errno = ERROR_NO_SUCH_DEVICE_INTERFACE
    114 )
    115 
    116 const (
    117 	MAX_DEVICE_ID_LEN   = 200
    118 	MAX_DEVNODE_ID_LEN  = MAX_DEVICE_ID_LEN
    119 	MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null
    120 	MAX_CLASS_NAME_LEN  = 32
    121 	MAX_PROFILE_LEN     = 80
    122 	MAX_CONFIG_VALUE    = 9999
    123 	MAX_INSTANCE_VALUE  = 9999
    124 	CONFIGMG_VERSION    = 0x0400
    125 )
    126 
    127 // Maximum string length constants
    128 const (
    129 	LINE_LEN                    = 256  // Windows 9x-compatible maximum for displayable strings coming from a device INF.
    130 	MAX_INF_STRING_LENGTH       = 4096 // Actual maximum size of an INF string (including string substitutions).
    131 	MAX_INF_SECTION_NAME_LENGTH = 255  // For Windows 9x compatibility, INF section names should be constrained to 32 characters.
    132 	MAX_TITLE_LEN               = 60
    133 	MAX_INSTRUCTION_LEN         = 256
    134 	MAX_LABEL_LEN               = 30
    135 	MAX_SERVICE_NAME_LEN        = 256
    136 	MAX_SUBTITLE_LEN            = 256
    137 )
    138 
    139 const (
    140 	// SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0").
    141 	SP_MAX_MACHINENAME_LENGTH = MAX_PATH + 3
    142 )
    143 
    144 // HSPFILEQ is type for setup file queue
    145 type HSPFILEQ uintptr
    146 
    147 // DevInfo holds reference to device information set
    148 type DevInfo Handle
    149 
    150 // DEVINST is a handle usually recognized by cfgmgr32 APIs
    151 type DEVINST uint32
    152 
    153 // DevInfoData is a device information structure (references a device instance that is a member of a device information set)
    154 type DevInfoData struct {
    155 	size      uint32
    156 	ClassGUID GUID
    157 	DevInst   DEVINST
    158 	_         uintptr
    159 }
    160 
    161 // DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass).
    162 type DevInfoListDetailData struct {
    163 	size                uint32 // Use unsafeSizeOf method
    164 	ClassGUID           GUID
    165 	RemoteMachineHandle Handle
    166 	remoteMachineName   [SP_MAX_MACHINENAME_LENGTH]uint16
    167 }
    168 
    169 func (*DevInfoListDetailData) unsafeSizeOf() uint32 {
    170 	if unsafe.Sizeof(uintptr(0)) == 4 {
    171 		// Windows declares this with pshpack1.h
    172 		return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName))
    173 	}
    174 	return uint32(unsafe.Sizeof(DevInfoListDetailData{}))
    175 }
    176 
    177 func (data *DevInfoListDetailData) RemoteMachineName() string {
    178 	return UTF16ToString(data.remoteMachineName[:])
    179 }
    180 
    181 func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error {
    182 	str, err := UTF16FromString(remoteMachineName)
    183 	if err != nil {
    184 		return err
    185 	}
    186 	copy(data.remoteMachineName[:], str)
    187 	return nil
    188 }
    189 
    190 // DI_FUNCTION is function type for device installer
    191 type DI_FUNCTION uint32
    192 
    193 const (
    194 	DIF_SELECTDEVICE                   DI_FUNCTION = 0x00000001
    195 	DIF_INSTALLDEVICE                  DI_FUNCTION = 0x00000002
    196 	DIF_ASSIGNRESOURCES                DI_FUNCTION = 0x00000003
    197 	DIF_PROPERTIES                     DI_FUNCTION = 0x00000004
    198 	DIF_REMOVE                         DI_FUNCTION = 0x00000005
    199 	DIF_FIRSTTIMESETUP                 DI_FUNCTION = 0x00000006
    200 	DIF_FOUNDDEVICE                    DI_FUNCTION = 0x00000007
    201 	DIF_SELECTCLASSDRIVERS             DI_FUNCTION = 0x00000008
    202 	DIF_VALIDATECLASSDRIVERS           DI_FUNCTION = 0x00000009
    203 	DIF_INSTALLCLASSDRIVERS            DI_FUNCTION = 0x0000000A
    204 	DIF_CALCDISKSPACE                  DI_FUNCTION = 0x0000000B
    205 	DIF_DESTROYPRIVATEDATA             DI_FUNCTION = 0x0000000C
    206 	DIF_VALIDATEDRIVER                 DI_FUNCTION = 0x0000000D
    207 	DIF_DETECT                         DI_FUNCTION = 0x0000000F
    208 	DIF_INSTALLWIZARD                  DI_FUNCTION = 0x00000010
    209 	DIF_DESTROYWIZARDDATA              DI_FUNCTION = 0x00000011
    210 	DIF_PROPERTYCHANGE                 DI_FUNCTION = 0x00000012
    211 	DIF_ENABLECLASS                    DI_FUNCTION = 0x00000013
    212 	DIF_DETECTVERIFY                   DI_FUNCTION = 0x00000014
    213 	DIF_INSTALLDEVICEFILES             DI_FUNCTION = 0x00000015
    214 	DIF_UNREMOVE                       DI_FUNCTION = 0x00000016
    215 	DIF_SELECTBESTCOMPATDRV            DI_FUNCTION = 0x00000017
    216 	DIF_ALLOW_INSTALL                  DI_FUNCTION = 0x00000018
    217 	DIF_REGISTERDEVICE                 DI_FUNCTION = 0x00000019
    218 	DIF_NEWDEVICEWIZARD_PRESELECT      DI_FUNCTION = 0x0000001A
    219 	DIF_NEWDEVICEWIZARD_SELECT         DI_FUNCTION = 0x0000001B
    220 	DIF_NEWDEVICEWIZARD_PREANALYZE     DI_FUNCTION = 0x0000001C
    221 	DIF_NEWDEVICEWIZARD_POSTANALYZE    DI_FUNCTION = 0x0000001D
    222 	DIF_NEWDEVICEWIZARD_FINISHINSTALL  DI_FUNCTION = 0x0000001E
    223 	DIF_INSTALLINTERFACES              DI_FUNCTION = 0x00000020
    224 	DIF_DETECTCANCEL                   DI_FUNCTION = 0x00000021
    225 	DIF_REGISTER_COINSTALLERS          DI_FUNCTION = 0x00000022
    226 	DIF_ADDPROPERTYPAGE_ADVANCED       DI_FUNCTION = 0x00000023
    227 	DIF_ADDPROPERTYPAGE_BASIC          DI_FUNCTION = 0x00000024
    228 	DIF_TROUBLESHOOTER                 DI_FUNCTION = 0x00000026
    229 	DIF_POWERMESSAGEWAKE               DI_FUNCTION = 0x00000027
    230 	DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028
    231 	DIF_UPDATEDRIVER_UI                DI_FUNCTION = 0x00000029
    232 	DIF_FINISHINSTALL_ACTION           DI_FUNCTION = 0x0000002A
    233 )
    234 
    235 // DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set)
    236 type DevInstallParams struct {
    237 	size                     uint32
    238 	Flags                    DI_FLAGS
    239 	FlagsEx                  DI_FLAGSEX
    240 	hwndParent               uintptr
    241 	InstallMsgHandler        uintptr
    242 	InstallMsgHandlerContext uintptr
    243 	FileQueue                HSPFILEQ
    244 	_                        uintptr
    245 	_                        uint32
    246 	driverPath               [MAX_PATH]uint16
    247 }
    248 
    249 func (params *DevInstallParams) DriverPath() string {
    250 	return UTF16ToString(params.driverPath[:])
    251 }
    252 
    253 func (params *DevInstallParams) SetDriverPath(driverPath string) error {
    254 	str, err := UTF16FromString(driverPath)
    255 	if err != nil {
    256 		return err
    257 	}
    258 	copy(params.driverPath[:], str)
    259 	return nil
    260 }
    261 
    262 // DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values
    263 type DI_FLAGS uint32
    264 
    265 const (
    266 	// Flags for choosing a device
    267 	DI_SHOWOEM       DI_FLAGS = 0x00000001 // support Other... button
    268 	DI_SHOWCOMPAT    DI_FLAGS = 0x00000002 // show compatibility list
    269 	DI_SHOWCLASS     DI_FLAGS = 0x00000004 // show class list
    270 	DI_SHOWALL       DI_FLAGS = 0x00000007 // both class & compat list shown
    271 	DI_NOVCP         DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue
    272 	DI_DIDCOMPAT     DI_FLAGS = 0x00000010 // Searched for compatible devices
    273 	DI_DIDCLASS      DI_FLAGS = 0x00000020 // Searched for class devices
    274 	DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible
    275 
    276 	// Flags returned by DiInstallDevice to indicate need to reboot/restart
    277 	DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect
    278 	DI_NEEDREBOOT  DI_FLAGS = 0x00000100 // ""
    279 
    280 	// Flags for device installation
    281 	DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk
    282 
    283 	// Flags set by DiBuildDriverInfoList
    284 	DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list
    285 
    286 	// Flag indicates that device is disabled
    287 	DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled
    288 
    289 	// Flags for Device/Class Properties
    290 	DI_GENERALPAGE_ADDED  DI_FLAGS = 0x00001000
    291 	DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000
    292 
    293 	// Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated.
    294 	DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000
    295 
    296 	// Flag to indicate that the sorting from the INF file should be used.
    297 	DI_INF_IS_SORTED DI_FLAGS = 0x00008000
    298 
    299 	// Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.
    300 	DI_ENUMSINGLEINF DI_FLAGS = 0x00010000
    301 
    302 	// Flag that prevents ConfigMgr from removing/re-enumerating devices during device
    303 	// registration, installation, and deletion.
    304 	DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000
    305 
    306 	// The following flag can be used to install a device disabled
    307 	DI_INSTALLDISABLED DI_FLAGS = 0x00040000
    308 
    309 	// Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver
    310 	// list from its existing class driver list, instead of the normal INF search.
    311 	DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000
    312 
    313 	// This flag is set if the Class Install params should be used.
    314 	DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000
    315 
    316 	// This flag is set if the caller of DiCallClassInstaller does NOT want the internal default action performed if the Class installer returns ERROR_DI_DO_DEFAULT.
    317 	DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000
    318 
    319 	// Flags for device installation
    320 	DI_QUIETINSTALL        DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info
    321 	DI_NOFILECOPY          DI_FLAGS = 0x01000000 // No file Copy necessary
    322 	DI_FORCECOPY           DI_FLAGS = 0x02000000 // Force files to be copied from install path
    323 	DI_DRIVERPAGE_ADDED    DI_FLAGS = 0x04000000 // Prop provider added Driver page.
    324 	DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg
    325 	DI_OVERRIDE_INFFLAGS   DI_FLAGS = 0x10000000 // Override INF flags
    326 	DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props
    327 
    328 	DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs
    329 
    330 	DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install
    331 )
    332 
    333 // DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values
    334 type DI_FLAGSEX uint32
    335 
    336 const (
    337 	DI_FLAGSEX_CI_FAILED                DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer
    338 	DI_FLAGSEX_FINISHINSTALL_ACTION     DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context.
    339 	DI_FLAGSEX_DIDINFOLIST              DI_FLAGSEX = 0x00000010 // Did the Class Info List
    340 	DI_FLAGSEX_DIDCOMPATINFO            DI_FLAGSEX = 0x00000020 // Did the Compat Info List
    341 	DI_FLAGSEX_FILTERCLASSES            DI_FLAGSEX = 0x00000040
    342 	DI_FLAGSEX_SETFAILEDINSTALL         DI_FLAGSEX = 0x00000080
    343 	DI_FLAGSEX_DEVICECHANGE             DI_FLAGSEX = 0x00000100
    344 	DI_FLAGSEX_ALWAYSWRITEIDS           DI_FLAGSEX = 0x00000200
    345 	DI_FLAGSEX_PROPCHANGE_PENDING       DI_FLAGSEX = 0x00000400 // One or more device property sheets have had changes made to them, and need to have a DIF_PROPERTYCHANGE occur.
    346 	DI_FLAGSEX_ALLOWEXCLUDEDDRVS        DI_FLAGSEX = 0x00000800
    347 	DI_FLAGSEX_NOUIONQUERYREMOVE        DI_FLAGSEX = 0x00001000
    348 	DI_FLAGSEX_USECLASSFORCOMPAT        DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.)
    349 	DI_FLAGSEX_NO_DRVREG_MODIFY         DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key.
    350 	DI_FLAGSEX_IN_SYSTEM_SETUP          DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup.
    351 	DI_FLAGSEX_INET_DRIVER              DI_FLAGSEX = 0x00020000 // Driver came from Windows Update
    352 	DI_FLAGSEX_APPENDDRIVERLIST         DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list.
    353 	DI_FLAGSEX_PREINSTALLBACKUP         DI_FLAGSEX = 0x00080000 // not used
    354 	DI_FLAGSEX_BACKUPONREPLACE          DI_FLAGSEX = 0x00100000 // not used
    355 	DI_FLAGSEX_DRIVERLIST_FROM_URL      DI_FLAGSEX = 0x00200000 // build driver list from INF(s) retrieved from URL specified in SP_DEVINSTALL_PARAMS.DriverPath (empty string means Windows Update website)
    356 	DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS DI_FLAGSEX = 0x00800000 // Don't include old Internet drivers when building a driver list. Ignored on Windows Vista and later.
    357 	DI_FLAGSEX_POWERPAGE_ADDED          DI_FLAGSEX = 0x01000000 // class installer added their own power page
    358 	DI_FLAGSEX_FILTERSIMILARDRIVERS     DI_FLAGSEX = 0x02000000 // only include similar drivers in class list
    359 	DI_FLAGSEX_INSTALLEDDRIVER          DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list.  Used in calls to SetupDiBuildDriverInfoList
    360 	DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE  DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list
    361 	DI_FLAGSEX_ALTPLATFORM_DRVSEARCH    DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue
    362 	DI_FLAGSEX_RESTART_DEVICE_ONLY      DI_FLAGSEX = 0x20000000 // only restart the device drivers are being installed on as opposed to restarting all devices using those drivers.
    363 	DI_FLAGSEX_RECURSIVESEARCH          DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search
    364 	DI_FLAGSEX_SEARCH_PUBLISHED_INFS    DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search
    365 )
    366 
    367 // ClassInstallHeader is the first member of any class install parameters structure. It contains the device installation request code that defines the format of the rest of the install parameters structure.
    368 type ClassInstallHeader struct {
    369 	size            uint32
    370 	InstallFunction DI_FUNCTION
    371 }
    372 
    373 func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader {
    374 	hdr := &ClassInstallHeader{InstallFunction: installFunction}
    375 	hdr.size = uint32(unsafe.Sizeof(*hdr))
    376 	return hdr
    377 }
    378 
    379 // DICS_STATE specifies values indicating a change in a device's state
    380 type DICS_STATE uint32
    381 
    382 const (
    383 	DICS_ENABLE     DICS_STATE = 0x00000001 // The device is being enabled.
    384 	DICS_DISABLE    DICS_STATE = 0x00000002 // The device is being disabled.
    385 	DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed.
    386 	DICS_START      DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile).
    387 	DICS_STOP       DICS_STATE = 0x00000005 // The device is being stopped. The driver stack will be unloaded and the CSCONFIGFLAG_DO_NOT_START flag will be set for the device.
    388 )
    389 
    390 // DICS_FLAG specifies the scope of a device property change
    391 type DICS_FLAG uint32
    392 
    393 const (
    394 	DICS_FLAG_GLOBAL         DICS_FLAG = 0x00000001 // make change in all hardware profiles
    395 	DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only
    396 	DICS_FLAG_CONFIGGENERAL  DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete)
    397 )
    398 
    399 // PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function.
    400 type PropChangeParams struct {
    401 	ClassInstallHeader ClassInstallHeader
    402 	StateChange        DICS_STATE
    403 	Scope              DICS_FLAG
    404 	HwProfile          uint32
    405 }
    406 
    407 // DI_REMOVEDEVICE specifies the scope of the device removal
    408 type DI_REMOVEDEVICE uint32
    409 
    410 const (
    411 	DI_REMOVEDEVICE_GLOBAL         DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry.
    412 	DI_REMOVEDEVICE_CONFIGSPECIFIC DI_REMOVEDEVICE = 0x00000002 // Make this change to only the hardware profile specified by HwProfile. this flag only applies to root-enumerated devices. When Windows removes the device from the last hardware profile in which it was configured, Windows performs a global removal.
    413 )
    414 
    415 // RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function.
    416 type RemoveDeviceParams struct {
    417 	ClassInstallHeader ClassInstallHeader
    418 	Scope              DI_REMOVEDEVICE
    419 	HwProfile          uint32
    420 }
    421 
    422 // DrvInfoData is driver information structure (member of a driver info list that may be associated with a particular device instance, or (globally) with a device information set)
    423 type DrvInfoData struct {
    424 	size          uint32
    425 	DriverType    uint32
    426 	_             uintptr
    427 	description   [LINE_LEN]uint16
    428 	mfgName       [LINE_LEN]uint16
    429 	providerName  [LINE_LEN]uint16
    430 	DriverDate    Filetime
    431 	DriverVersion uint64
    432 }
    433 
    434 func (data *DrvInfoData) Description() string {
    435 	return UTF16ToString(data.description[:])
    436 }
    437 
    438 func (data *DrvInfoData) SetDescription(description string) error {
    439 	str, err := UTF16FromString(description)
    440 	if err != nil {
    441 		return err
    442 	}
    443 	copy(data.description[:], str)
    444 	return nil
    445 }
    446 
    447 func (data *DrvInfoData) MfgName() string {
    448 	return UTF16ToString(data.mfgName[:])
    449 }
    450 
    451 func (data *DrvInfoData) SetMfgName(mfgName string) error {
    452 	str, err := UTF16FromString(mfgName)
    453 	if err != nil {
    454 		return err
    455 	}
    456 	copy(data.mfgName[:], str)
    457 	return nil
    458 }
    459 
    460 func (data *DrvInfoData) ProviderName() string {
    461 	return UTF16ToString(data.providerName[:])
    462 }
    463 
    464 func (data *DrvInfoData) SetProviderName(providerName string) error {
    465 	str, err := UTF16FromString(providerName)
    466 	if err != nil {
    467 		return err
    468 	}
    469 	copy(data.providerName[:], str)
    470 	return nil
    471 }
    472 
    473 // IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters.
    474 func (data *DrvInfoData) IsNewer(driverDate Filetime, driverVersion uint64) bool {
    475 	if data.DriverDate.HighDateTime > driverDate.HighDateTime {
    476 		return true
    477 	}
    478 	if data.DriverDate.HighDateTime < driverDate.HighDateTime {
    479 		return false
    480 	}
    481 
    482 	if data.DriverDate.LowDateTime > driverDate.LowDateTime {
    483 		return true
    484 	}
    485 	if data.DriverDate.LowDateTime < driverDate.LowDateTime {
    486 		return false
    487 	}
    488 
    489 	if data.DriverVersion > driverVersion {
    490 		return true
    491 	}
    492 	if data.DriverVersion < driverVersion {
    493 		return false
    494 	}
    495 
    496 	return false
    497 }
    498 
    499 // DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure)
    500 type DrvInfoDetailData struct {
    501 	size            uint32 // Use unsafeSizeOf method
    502 	InfDate         Filetime
    503 	compatIDsOffset uint32
    504 	compatIDsLength uint32
    505 	_               uintptr
    506 	sectionName     [LINE_LEN]uint16
    507 	infFileName     [MAX_PATH]uint16
    508 	drvDescription  [LINE_LEN]uint16
    509 	hardwareID      [1]uint16
    510 }
    511 
    512 func (*DrvInfoDetailData) unsafeSizeOf() uint32 {
    513 	if unsafe.Sizeof(uintptr(0)) == 4 {
    514 		// Windows declares this with pshpack1.h
    515 		return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID))
    516 	}
    517 	return uint32(unsafe.Sizeof(DrvInfoDetailData{}))
    518 }
    519 
    520 func (data *DrvInfoDetailData) SectionName() string {
    521 	return UTF16ToString(data.sectionName[:])
    522 }
    523 
    524 func (data *DrvInfoDetailData) InfFileName() string {
    525 	return UTF16ToString(data.infFileName[:])
    526 }
    527 
    528 func (data *DrvInfoDetailData) DrvDescription() string {
    529 	return UTF16ToString(data.drvDescription[:])
    530 }
    531 
    532 func (data *DrvInfoDetailData) HardwareID() string {
    533 	if data.compatIDsOffset > 1 {
    534 		bufW := data.getBuf()
    535 		return UTF16ToString(bufW[:wcslen(bufW)])
    536 	}
    537 
    538 	return ""
    539 }
    540 
    541 func (data *DrvInfoDetailData) CompatIDs() []string {
    542 	a := make([]string, 0)
    543 
    544 	if data.compatIDsLength > 0 {
    545 		bufW := data.getBuf()
    546 		bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength]
    547 		for i := 0; i < len(bufW); {
    548 			j := i + wcslen(bufW[i:])
    549 			if i < j {
    550 				a = append(a, UTF16ToString(bufW[i:j]))
    551 			}
    552 			i = j + 1
    553 		}
    554 	}
    555 
    556 	return a
    557 }
    558 
    559 func (data *DrvInfoDetailData) getBuf() []uint16 {
    560 	len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2
    561 	sl := struct {
    562 		addr *uint16
    563 		len  int
    564 		cap  int
    565 	}{&data.hardwareID[0], int(len), int(len)}
    566 	return *(*[]uint16)(unsafe.Pointer(&sl))
    567 }
    568 
    569 // IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list.
    570 func (data *DrvInfoDetailData) IsCompatible(hwid string) bool {
    571 	hwidLC := strings.ToLower(hwid)
    572 	if strings.ToLower(data.HardwareID()) == hwidLC {
    573 		return true
    574 	}
    575 	a := data.CompatIDs()
    576 	for i := range a {
    577 		if strings.ToLower(a[i]) == hwidLC {
    578 			return true
    579 		}
    580 	}
    581 
    582 	return false
    583 }
    584 
    585 // DICD flags control SetupDiCreateDeviceInfo
    586 type DICD uint32
    587 
    588 const (
    589 	DICD_GENERATE_ID       DICD = 0x00000001
    590 	DICD_INHERIT_CLASSDRVS DICD = 0x00000002
    591 )
    592 
    593 // SUOI flags control SetupUninstallOEMInf
    594 type SUOI uint32
    595 
    596 const (
    597 	SUOI_FORCEDELETE SUOI = 0x0001
    598 )
    599 
    600 // SPDIT flags to distinguish between class drivers and
    601 // device drivers. (Passed in 'DriverType' parameter of
    602 // driver information list APIs)
    603 type SPDIT uint32
    604 
    605 const (
    606 	SPDIT_NODRIVER     SPDIT = 0x00000000
    607 	SPDIT_CLASSDRIVER  SPDIT = 0x00000001
    608 	SPDIT_COMPATDRIVER SPDIT = 0x00000002
    609 )
    610 
    611 // DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs
    612 type DIGCF uint32
    613 
    614 const (
    615 	DIGCF_DEFAULT         DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE
    616 	DIGCF_PRESENT         DIGCF = 0x00000002
    617 	DIGCF_ALLCLASSES      DIGCF = 0x00000004
    618 	DIGCF_PROFILE         DIGCF = 0x00000008
    619 	DIGCF_DEVICEINTERFACE DIGCF = 0x00000010
    620 )
    621 
    622 // DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey.
    623 type DIREG uint32
    624 
    625 const (
    626 	DIREG_DEV  DIREG = 0x00000001 // Open/Create/Delete device key
    627 	DIREG_DRV  DIREG = 0x00000002 // Open/Create/Delete driver key
    628 	DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key
    629 )
    630 
    631 // SPDRP specifies device registry property codes
    632 // (Codes marked as read-only (R) may only be used for
    633 // SetupDiGetDeviceRegistryProperty)
    634 //
    635 // These values should cover the same set of registry properties
    636 // as defined by the CM_DRP codes in cfgmgr32.h.
    637 //
    638 // Note that SPDRP codes are zero based while CM_DRP codes are one based!
    639 type SPDRP uint32
    640 
    641 const (
    642 	SPDRP_DEVICEDESC                  SPDRP = 0x00000000 // DeviceDesc (R/W)
    643 	SPDRP_HARDWAREID                  SPDRP = 0x00000001 // HardwareID (R/W)
    644 	SPDRP_COMPATIBLEIDS               SPDRP = 0x00000002 // CompatibleIDs (R/W)
    645 	SPDRP_SERVICE                     SPDRP = 0x00000004 // Service (R/W)
    646 	SPDRP_CLASS                       SPDRP = 0x00000007 // Class (R--tied to ClassGUID)
    647 	SPDRP_CLASSGUID                   SPDRP = 0x00000008 // ClassGUID (R/W)
    648 	SPDRP_DRIVER                      SPDRP = 0x00000009 // Driver (R/W)
    649 	SPDRP_CONFIGFLAGS                 SPDRP = 0x0000000A // ConfigFlags (R/W)
    650 	SPDRP_MFG                         SPDRP = 0x0000000B // Mfg (R/W)
    651 	SPDRP_FRIENDLYNAME                SPDRP = 0x0000000C // FriendlyName (R/W)
    652 	SPDRP_LOCATION_INFORMATION        SPDRP = 0x0000000D // LocationInformation (R/W)
    653 	SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R)
    654 	SPDRP_CAPABILITIES                SPDRP = 0x0000000F // Capabilities (R)
    655 	SPDRP_UI_NUMBER                   SPDRP = 0x00000010 // UiNumber (R)
    656 	SPDRP_UPPERFILTERS                SPDRP = 0x00000011 // UpperFilters (R/W)
    657 	SPDRP_LOWERFILTERS                SPDRP = 0x00000012 // LowerFilters (R/W)
    658 	SPDRP_BUSTYPEGUID                 SPDRP = 0x00000013 // BusTypeGUID (R)
    659 	SPDRP_LEGACYBUSTYPE               SPDRP = 0x00000014 // LegacyBusType (R)
    660 	SPDRP_BUSNUMBER                   SPDRP = 0x00000015 // BusNumber (R)
    661 	SPDRP_ENUMERATOR_NAME             SPDRP = 0x00000016 // Enumerator Name (R)
    662 	SPDRP_SECURITY                    SPDRP = 0x00000017 // Security (R/W, binary form)
    663 	SPDRP_SECURITY_SDS                SPDRP = 0x00000018 // Security (W, SDS form)
    664 	SPDRP_DEVTYPE                     SPDRP = 0x00000019 // Device Type (R/W)
    665 	SPDRP_EXCLUSIVE                   SPDRP = 0x0000001A // Device is exclusive-access (R/W)
    666 	SPDRP_CHARACTERISTICS             SPDRP = 0x0000001B // Device Characteristics (R/W)
    667 	SPDRP_ADDRESS                     SPDRP = 0x0000001C // Device Address (R)
    668 	SPDRP_UI_NUMBER_DESC_FORMAT       SPDRP = 0x0000001D // UiNumberDescFormat (R/W)
    669 	SPDRP_DEVICE_POWER_DATA           SPDRP = 0x0000001E // Device Power Data (R)
    670 	SPDRP_REMOVAL_POLICY              SPDRP = 0x0000001F // Removal Policy (R)
    671 	SPDRP_REMOVAL_POLICY_HW_DEFAULT   SPDRP = 0x00000020 // Hardware Removal Policy (R)
    672 	SPDRP_REMOVAL_POLICY_OVERRIDE     SPDRP = 0x00000021 // Removal Policy Override (RW)
    673 	SPDRP_INSTALL_STATE               SPDRP = 0x00000022 // Device Install State (R)
    674 	SPDRP_LOCATION_PATHS              SPDRP = 0x00000023 // Device Location Paths (R)
    675 	SPDRP_BASE_CONTAINERID            SPDRP = 0x00000024 // Base ContainerID (R)
    676 
    677 	SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals
    678 )
    679 
    680 // DEVPROPTYPE represents the property-data-type identifier that specifies the
    681 // data type of a device property value in the unified device property model.
    682 type DEVPROPTYPE uint32
    683 
    684 const (
    685 	DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000
    686 	DEVPROP_TYPEMOD_LIST  DEVPROPTYPE = 0x00002000
    687 
    688 	DEVPROP_TYPE_EMPTY                      DEVPROPTYPE = 0x00000000
    689 	DEVPROP_TYPE_NULL                       DEVPROPTYPE = 0x00000001
    690 	DEVPROP_TYPE_SBYTE                      DEVPROPTYPE = 0x00000002
    691 	DEVPROP_TYPE_BYTE                       DEVPROPTYPE = 0x00000003
    692 	DEVPROP_TYPE_INT16                      DEVPROPTYPE = 0x00000004
    693 	DEVPROP_TYPE_UINT16                     DEVPROPTYPE = 0x00000005
    694 	DEVPROP_TYPE_INT32                      DEVPROPTYPE = 0x00000006
    695 	DEVPROP_TYPE_UINT32                     DEVPROPTYPE = 0x00000007
    696 	DEVPROP_TYPE_INT64                      DEVPROPTYPE = 0x00000008
    697 	DEVPROP_TYPE_UINT64                     DEVPROPTYPE = 0x00000009
    698 	DEVPROP_TYPE_FLOAT                      DEVPROPTYPE = 0x0000000A
    699 	DEVPROP_TYPE_DOUBLE                     DEVPROPTYPE = 0x0000000B
    700 	DEVPROP_TYPE_DECIMAL                    DEVPROPTYPE = 0x0000000C
    701 	DEVPROP_TYPE_GUID                       DEVPROPTYPE = 0x0000000D
    702 	DEVPROP_TYPE_CURRENCY                   DEVPROPTYPE = 0x0000000E
    703 	DEVPROP_TYPE_DATE                       DEVPROPTYPE = 0x0000000F
    704 	DEVPROP_TYPE_FILETIME                   DEVPROPTYPE = 0x00000010
    705 	DEVPROP_TYPE_BOOLEAN                    DEVPROPTYPE = 0x00000011
    706 	DEVPROP_TYPE_STRING                     DEVPROPTYPE = 0x00000012
    707 	DEVPROP_TYPE_STRING_LIST                DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST
    708 	DEVPROP_TYPE_SECURITY_DESCRIPTOR        DEVPROPTYPE = 0x00000013
    709 	DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014
    710 	DEVPROP_TYPE_DEVPROPKEY                 DEVPROPTYPE = 0x00000015
    711 	DEVPROP_TYPE_DEVPROPTYPE                DEVPROPTYPE = 0x00000016
    712 	DEVPROP_TYPE_BINARY                     DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY
    713 	DEVPROP_TYPE_ERROR                      DEVPROPTYPE = 0x00000017
    714 	DEVPROP_TYPE_NTSTATUS                   DEVPROPTYPE = 0x00000018
    715 	DEVPROP_TYPE_STRING_INDIRECT            DEVPROPTYPE = 0x00000019
    716 
    717 	MAX_DEVPROP_TYPE    DEVPROPTYPE = 0x00000019
    718 	MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000
    719 
    720 	DEVPROP_MASK_TYPE    DEVPROPTYPE = 0x00000FFF
    721 	DEVPROP_MASK_TYPEMOD DEVPROPTYPE = 0x0000F000
    722 )
    723 
    724 // DEVPROPGUID specifies a property category.
    725 type DEVPROPGUID GUID
    726 
    727 // DEVPROPID uniquely identifies the property within the property category.
    728 type DEVPROPID uint32
    729 
    730 const DEVPROPID_FIRST_USABLE DEVPROPID = 2
    731 
    732 // DEVPROPKEY represents a device property key for a device property in the
    733 // unified device property model.
    734 type DEVPROPKEY struct {
    735 	FmtID DEVPROPGUID
    736 	PID   DEVPROPID
    737 }
    738 
    739 // CONFIGRET is a return value or error code from cfgmgr32 APIs
    740 type CONFIGRET uint32
    741 
    742 func (ret CONFIGRET) Error() string {
    743 	if win32Error, ok := ret.Unwrap().(Errno); ok {
    744 		return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret))
    745 	}
    746 	return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret))
    747 }
    748 
    749 func (ret CONFIGRET) Win32Error(defaultError Errno) Errno {
    750 	return cm_MapCrToWin32Err(ret, defaultError)
    751 }
    752 
    753 func (ret CONFIGRET) Unwrap() error {
    754 	const noMatch = Errno(^uintptr(0))
    755 	win32Error := ret.Win32Error(noMatch)
    756 	if win32Error == noMatch {
    757 		return nil
    758 	}
    759 	return win32Error
    760 }
    761 
    762 const (
    763 	CR_SUCCESS                  CONFIGRET = 0x00000000
    764 	CR_DEFAULT                  CONFIGRET = 0x00000001
    765 	CR_OUT_OF_MEMORY            CONFIGRET = 0x00000002
    766 	CR_INVALID_POINTER          CONFIGRET = 0x00000003
    767 	CR_INVALID_FLAG             CONFIGRET = 0x00000004
    768 	CR_INVALID_DEVNODE          CONFIGRET = 0x00000005
    769 	CR_INVALID_DEVINST                    = CR_INVALID_DEVNODE
    770 	CR_INVALID_RES_DES          CONFIGRET = 0x00000006
    771 	CR_INVALID_LOG_CONF         CONFIGRET = 0x00000007
    772 	CR_INVALID_ARBITRATOR       CONFIGRET = 0x00000008
    773 	CR_INVALID_NODELIST         CONFIGRET = 0x00000009
    774 	CR_DEVNODE_HAS_REQS         CONFIGRET = 0x0000000A
    775 	CR_DEVINST_HAS_REQS                   = CR_DEVNODE_HAS_REQS
    776 	CR_INVALID_RESOURCEID       CONFIGRET = 0x0000000B
    777 	CR_DLVXD_NOT_FOUND          CONFIGRET = 0x0000000C
    778 	CR_NO_SUCH_DEVNODE          CONFIGRET = 0x0000000D
    779 	CR_NO_SUCH_DEVINST                    = CR_NO_SUCH_DEVNODE
    780 	CR_NO_MORE_LOG_CONF         CONFIGRET = 0x0000000E
    781 	CR_NO_MORE_RES_DES          CONFIGRET = 0x0000000F
    782 	CR_ALREADY_SUCH_DEVNODE     CONFIGRET = 0x00000010
    783 	CR_ALREADY_SUCH_DEVINST               = CR_ALREADY_SUCH_DEVNODE
    784 	CR_INVALID_RANGE_LIST       CONFIGRET = 0x00000011
    785 	CR_INVALID_RANGE            CONFIGRET = 0x00000012
    786 	CR_FAILURE                  CONFIGRET = 0x00000013
    787 	CR_NO_SUCH_LOGICAL_DEV      CONFIGRET = 0x00000014
    788 	CR_CREATE_BLOCKED           CONFIGRET = 0x00000015
    789 	CR_NOT_SYSTEM_VM            CONFIGRET = 0x00000016
    790 	CR_REMOVE_VETOED            CONFIGRET = 0x00000017
    791 	CR_APM_VETOED               CONFIGRET = 0x00000018
    792 	CR_INVALID_LOAD_TYPE        CONFIGRET = 0x00000019
    793 	CR_BUFFER_SMALL             CONFIGRET = 0x0000001A
    794 	CR_NO_ARBITRATOR            CONFIGRET = 0x0000001B
    795 	CR_NO_REGISTRY_HANDLE       CONFIGRET = 0x0000001C
    796 	CR_REGISTRY_ERROR           CONFIGRET = 0x0000001D
    797 	CR_INVALID_DEVICE_ID        CONFIGRET = 0x0000001E
    798 	CR_INVALID_DATA             CONFIGRET = 0x0000001F
    799 	CR_INVALID_API              CONFIGRET = 0x00000020
    800 	CR_DEVLOADER_NOT_READY      CONFIGRET = 0x00000021
    801 	CR_NEED_RESTART             CONFIGRET = 0x00000022
    802 	CR_NO_MORE_HW_PROFILES      CONFIGRET = 0x00000023
    803 	CR_DEVICE_NOT_THERE         CONFIGRET = 0x00000024
    804 	CR_NO_SUCH_VALUE            CONFIGRET = 0x00000025
    805 	CR_WRONG_TYPE               CONFIGRET = 0x00000026
    806 	CR_INVALID_PRIORITY         CONFIGRET = 0x00000027
    807 	CR_NOT_DISABLEABLE          CONFIGRET = 0x00000028
    808 	CR_FREE_RESOURCES           CONFIGRET = 0x00000029
    809 	CR_QUERY_VETOED             CONFIGRET = 0x0000002A
    810 	CR_CANT_SHARE_IRQ           CONFIGRET = 0x0000002B
    811 	CR_NO_DEPENDENT             CONFIGRET = 0x0000002C
    812 	CR_SAME_RESOURCES           CONFIGRET = 0x0000002D
    813 	CR_NO_SUCH_REGISTRY_KEY     CONFIGRET = 0x0000002E
    814 	CR_INVALID_MACHINENAME      CONFIGRET = 0x0000002F
    815 	CR_REMOTE_COMM_FAILURE      CONFIGRET = 0x00000030
    816 	CR_MACHINE_UNAVAILABLE      CONFIGRET = 0x00000031
    817 	CR_NO_CM_SERVICES           CONFIGRET = 0x00000032
    818 	CR_ACCESS_DENIED            CONFIGRET = 0x00000033
    819 	CR_CALL_NOT_IMPLEMENTED     CONFIGRET = 0x00000034
    820 	CR_INVALID_PROPERTY         CONFIGRET = 0x00000035
    821 	CR_DEVICE_INTERFACE_ACTIVE  CONFIGRET = 0x00000036
    822 	CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037
    823 	CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038
    824 	CR_INVALID_CONFLICT_LIST    CONFIGRET = 0x00000039
    825 	CR_INVALID_INDEX            CONFIGRET = 0x0000003A
    826 	CR_INVALID_STRUCTURE_SIZE   CONFIGRET = 0x0000003B
    827 	NUM_CR_RESULTS              CONFIGRET = 0x0000003C
    828 )
    829 
    830 const (
    831 	CM_GET_DEVICE_INTERFACE_LIST_PRESENT     = 0 // only currently 'live' device interfaces
    832 	CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not
    833 )
    834 
    835 const (
    836 	DN_ROOT_ENUMERATED       = 0x00000001        // Was enumerated by ROOT
    837 	DN_DRIVER_LOADED         = 0x00000002        // Has Register_Device_Driver
    838 	DN_ENUM_LOADED           = 0x00000004        // Has Register_Enumerator
    839 	DN_STARTED               = 0x00000008        // Is currently configured
    840 	DN_MANUAL                = 0x00000010        // Manually installed
    841 	DN_NEED_TO_ENUM          = 0x00000020        // May need reenumeration
    842 	DN_NOT_FIRST_TIME        = 0x00000040        // Has received a config
    843 	DN_HARDWARE_ENUM         = 0x00000080        // Enum generates hardware ID
    844 	DN_LIAR                  = 0x00000100        // Lied about can reconfig once
    845 	DN_HAS_MARK              = 0x00000200        // Not CM_Create_DevInst lately
    846 	DN_HAS_PROBLEM           = 0x00000400        // Need device installer
    847 	DN_FILTERED              = 0x00000800        // Is filtered
    848 	DN_MOVED                 = 0x00001000        // Has been moved
    849 	DN_DISABLEABLE           = 0x00002000        // Can be disabled
    850 	DN_REMOVABLE             = 0x00004000        // Can be removed
    851 	DN_PRIVATE_PROBLEM       = 0x00008000        // Has a private problem
    852 	DN_MF_PARENT             = 0x00010000        // Multi function parent
    853 	DN_MF_CHILD              = 0x00020000        // Multi function child
    854 	DN_WILL_BE_REMOVED       = 0x00040000        // DevInst is being removed
    855 	DN_NOT_FIRST_TIMEE       = 0x00080000        // Has received a config enumerate
    856 	DN_STOP_FREE_RES         = 0x00100000        // When child is stopped, free resources
    857 	DN_REBAL_CANDIDATE       = 0x00200000        // Don't skip during rebalance
    858 	DN_BAD_PARTIAL           = 0x00400000        // This devnode's log_confs do not have same resources
    859 	DN_NT_ENUMERATOR         = 0x00800000        // This devnode's is an NT enumerator
    860 	DN_NT_DRIVER             = 0x01000000        // This devnode's is an NT driver
    861 	DN_NEEDS_LOCKING         = 0x02000000        // Devnode need lock resume processing
    862 	DN_ARM_WAKEUP            = 0x04000000        // Devnode can be the wakeup device
    863 	DN_APM_ENUMERATOR        = 0x08000000        // APM aware enumerator
    864 	DN_APM_DRIVER            = 0x10000000        // APM aware driver
    865 	DN_SILENT_INSTALL        = 0x20000000        // Silent install
    866 	DN_NO_SHOW_IN_DM         = 0x40000000        // No show in device manager
    867 	DN_BOOT_LOG_PROB         = 0x80000000        // Had a problem during preassignment of boot log conf
    868 	DN_NEED_RESTART          = DN_LIAR           // System needs to be restarted for this Devnode to work properly
    869 	DN_DRIVER_BLOCKED        = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode
    870 	DN_LEGACY_DRIVER         = DN_MOVED          // This device is using a legacy driver
    871 	DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK       // One or more children have invalid IDs
    872 	DN_DEVICE_DISCONNECTED   = DN_NEEDS_LOCKING  // The function driver for a device reported that the device is not connected.  Typically this means a wireless device is out of range.
    873 	DN_QUERY_REMOVE_PENDING  = DN_MF_PARENT      // Device is part of a set of related devices collectively pending query-removal
    874 	DN_QUERY_REMOVE_ACTIVE   = DN_MF_CHILD       // Device is actively engaged in a query-remove IRP
    875 	DN_CHANGEABLE_FLAGS      = DN_NOT_FIRST_TIME | DN_HARDWARE_ENUM | DN_HAS_MARK | DN_DISABLEABLE | DN_REMOVABLE | DN_MF_CHILD | DN_MF_PARENT | DN_NOT_FIRST_TIMEE | DN_STOP_FREE_RES | DN_REBAL_CANDIDATE | DN_NT_ENUMERATOR | DN_NT_DRIVER | DN_SILENT_INSTALL | DN_NO_SHOW_IN_DM
    876 )
    877 
    878 //sys	setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW
    879 
    880 // 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.
    881 func SetupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) {
    882 	var machineNameUTF16 *uint16
    883 	if machineName != "" {
    884 		machineNameUTF16, err = UTF16PtrFromString(machineName)
    885 		if err != nil {
    886 			return
    887 		}
    888 	}
    889 	return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0)
    890 }
    891 
    892 //sys	setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW
    893 
    894 // SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
    895 func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) {
    896 	data := &DevInfoListDetailData{}
    897 	data.size = data.unsafeSizeOf()
    898 
    899 	return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data)
    900 }
    901 
    902 // DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
    903 func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) {
    904 	return SetupDiGetDeviceInfoListDetail(deviceInfoSet)
    905 }
    906 
    907 //sys	setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW
    908 
    909 // SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set.
    910 func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) {
    911 	deviceNameUTF16, err := UTF16PtrFromString(deviceName)
    912 	if err != nil {
    913 		return
    914 	}
    915 
    916 	var deviceDescriptionUTF16 *uint16
    917 	if deviceDescription != "" {
    918 		deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription)
    919 		if err != nil {
    920 			return
    921 		}
    922 	}
    923 
    924 	data := &DevInfoData{}
    925 	data.size = uint32(unsafe.Sizeof(*data))
    926 
    927 	return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data)
    928 }
    929 
    930 // CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set.
    931 func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) {
    932 	return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags)
    933 }
    934 
    935 //sys	setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo
    936 
    937 // SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set.
    938 func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) {
    939 	data := &DevInfoData{}
    940 	data.size = uint32(unsafe.Sizeof(*data))
    941 
    942 	return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data)
    943 }
    944 
    945 // EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set.
    946 func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) {
    947 	return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex)
    948 }
    949 
    950 // SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.
    951 //sys	SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList
    952 
    953 // Close method deletes a device information set and frees all associated memory.
    954 func (deviceInfoSet DevInfo) Close() error {
    955 	return SetupDiDestroyDeviceInfoList(deviceInfoSet)
    956 }
    957 
    958 //sys	SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList
    959 
    960 // 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.
    961 func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
    962 	return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
    963 }
    964 
    965 //sys	SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch
    966 
    967 // CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread.
    968 func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error {
    969 	return SetupDiCancelDriverInfoSearch(deviceInfoSet)
    970 }
    971 
    972 //sys	setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW
    973 
    974 // SetupDiEnumDriverInfo function enumerates the members of a driver list.
    975 func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
    976 	data := &DrvInfoData{}
    977 	data.size = uint32(unsafe.Sizeof(*data))
    978 
    979 	return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data)
    980 }
    981 
    982 // EnumDriverInfo method enumerates the members of a driver list.
    983 func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
    984 	return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex)
    985 }
    986 
    987 //sys	setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW
    988 
    989 // SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element.
    990 func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) {
    991 	data := &DrvInfoData{}
    992 	data.size = uint32(unsafe.Sizeof(*data))
    993 
    994 	return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data)
    995 }
    996 
    997 // SelectedDriver method retrieves the selected driver for a device information set or a particular device information element.
    998 func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) {
    999 	return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData)
   1000 }
   1001 
   1002 //sys	SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW
   1003 
   1004 // SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.
   1005 func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error {
   1006 	return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData)
   1007 }
   1008 
   1009 //sys	setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW
   1010 
   1011 // SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.
   1012 func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
   1013 	reqSize := uint32(2048)
   1014 	for {
   1015 		buf := make([]byte, reqSize)
   1016 		data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
   1017 		data.size = data.unsafeSizeOf()
   1018 		err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)
   1019 		if err == ERROR_INSUFFICIENT_BUFFER {
   1020 			continue
   1021 		}
   1022 		if err != nil {
   1023 			return nil, err
   1024 		}
   1025 		data.size = reqSize
   1026 		return data, nil
   1027 	}
   1028 }
   1029 
   1030 // DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set.
   1031 func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
   1032 	return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData)
   1033 }
   1034 
   1035 //sys	SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList
   1036 
   1037 // DestroyDriverInfoList method deletes a driver list.
   1038 func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
   1039 	return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
   1040 }
   1041 
   1042 //sys	setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiGetClassDevsExW
   1043 
   1044 // SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer.
   1045 func SetupDiGetClassDevsEx(classGUID *GUID, enumerator string, hwndParent uintptr, flags DIGCF, deviceInfoSet DevInfo, machineName string) (handle DevInfo, err error) {
   1046 	var enumeratorUTF16 *uint16
   1047 	if enumerator != "" {
   1048 		enumeratorUTF16, err = UTF16PtrFromString(enumerator)
   1049 		if err != nil {
   1050 			return
   1051 		}
   1052 	}
   1053 	var machineNameUTF16 *uint16
   1054 	if machineName != "" {
   1055 		machineNameUTF16, err = UTF16PtrFromString(machineName)
   1056 		if err != nil {
   1057 			return
   1058 		}
   1059 	}
   1060 	return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0)
   1061 }
   1062 
   1063 // SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
   1064 //sys	SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller
   1065 
   1066 // CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
   1067 func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error {
   1068 	return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData)
   1069 }
   1070 
   1071 // SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.
   1072 //sys	SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) [failretval==InvalidHandle] = setupapi.SetupDiOpenDevRegKey
   1073 
   1074 // OpenDevRegKey method opens a registry key for device-specific configuration information.
   1075 func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (Handle, error) {
   1076 	return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired)
   1077 }
   1078 
   1079 //sys	setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) = setupapi.SetupDiGetDevicePropertyW
   1080 
   1081 // SetupDiGetDeviceProperty function retrieves a specified device instance property.
   1082 func SetupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY) (value interface{}, err error) {
   1083 	reqSize := uint32(256)
   1084 	for {
   1085 		var dataType DEVPROPTYPE
   1086 		buf := make([]byte, reqSize)
   1087 		err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0)
   1088 		if err == ERROR_INSUFFICIENT_BUFFER {
   1089 			continue
   1090 		}
   1091 		if err != nil {
   1092 			return
   1093 		}
   1094 		switch dataType {
   1095 		case DEVPROP_TYPE_STRING:
   1096 			ret := UTF16ToString(bufToUTF16(buf))
   1097 			runtime.KeepAlive(buf)
   1098 			return ret, nil
   1099 		}
   1100 		return nil, errors.New("unimplemented property type")
   1101 	}
   1102 }
   1103 
   1104 //sys	setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW
   1105 
   1106 // SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property.
   1107 func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) {
   1108 	reqSize := uint32(256)
   1109 	for {
   1110 		var dataType uint32
   1111 		buf := make([]byte, reqSize)
   1112 		err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)
   1113 		if err == ERROR_INSUFFICIENT_BUFFER {
   1114 			continue
   1115 		}
   1116 		if err != nil {
   1117 			return
   1118 		}
   1119 		return getRegistryValue(buf[:reqSize], dataType)
   1120 	}
   1121 }
   1122 
   1123 func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
   1124 	switch dataType {
   1125 	case REG_SZ:
   1126 		ret := UTF16ToString(bufToUTF16(buf))
   1127 		runtime.KeepAlive(buf)
   1128 		return ret, nil
   1129 	case REG_EXPAND_SZ:
   1130 		value := UTF16ToString(bufToUTF16(buf))
   1131 		if value == "" {
   1132 			return "", nil
   1133 		}
   1134 		p, err := syscall.UTF16PtrFromString(value)
   1135 		if err != nil {
   1136 			return "", err
   1137 		}
   1138 		ret := make([]uint16, 100)
   1139 		for {
   1140 			n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret)))
   1141 			if err != nil {
   1142 				return "", err
   1143 			}
   1144 			if n <= uint32(len(ret)) {
   1145 				return UTF16ToString(ret[:n]), nil
   1146 			}
   1147 			ret = make([]uint16, n)
   1148 		}
   1149 	case REG_BINARY:
   1150 		return buf, nil
   1151 	case REG_DWORD_LITTLE_ENDIAN:
   1152 		return binary.LittleEndian.Uint32(buf), nil
   1153 	case REG_DWORD_BIG_ENDIAN:
   1154 		return binary.BigEndian.Uint32(buf), nil
   1155 	case REG_MULTI_SZ:
   1156 		bufW := bufToUTF16(buf)
   1157 		a := []string{}
   1158 		for i := 0; i < len(bufW); {
   1159 			j := i + wcslen(bufW[i:])
   1160 			if i < j {
   1161 				a = append(a, UTF16ToString(bufW[i:j]))
   1162 			}
   1163 			i = j + 1
   1164 		}
   1165 		runtime.KeepAlive(buf)
   1166 		return a, nil
   1167 	case REG_QWORD_LITTLE_ENDIAN:
   1168 		return binary.LittleEndian.Uint64(buf), nil
   1169 	default:
   1170 		return nil, fmt.Errorf("Unsupported registry value type: %v", dataType)
   1171 	}
   1172 }
   1173 
   1174 // bufToUTF16 function reinterprets []byte buffer as []uint16
   1175 func bufToUTF16(buf []byte) []uint16 {
   1176 	sl := struct {
   1177 		addr *uint16
   1178 		len  int
   1179 		cap  int
   1180 	}{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2}
   1181 	return *(*[]uint16)(unsafe.Pointer(&sl))
   1182 }
   1183 
   1184 // utf16ToBuf function reinterprets []uint16 as []byte
   1185 func utf16ToBuf(buf []uint16) []byte {
   1186 	sl := struct {
   1187 		addr *byte
   1188 		len  int
   1189 		cap  int
   1190 	}{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2}
   1191 	return *(*[]byte)(unsafe.Pointer(&sl))
   1192 }
   1193 
   1194 func wcslen(str []uint16) int {
   1195 	for i := 0; i < len(str); i++ {
   1196 		if str[i] == 0 {
   1197 			return i
   1198 		}
   1199 	}
   1200 	return len(str)
   1201 }
   1202 
   1203 // DeviceRegistryProperty method retrieves a specified Plug and Play device property.
   1204 func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) {
   1205 	return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property)
   1206 }
   1207 
   1208 //sys	setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW
   1209 
   1210 // SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device.
   1211 func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
   1212 	return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers)))
   1213 }
   1214 
   1215 // SetDeviceRegistryProperty function sets a Plug and Play device property for a device.
   1216 func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
   1217 	return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)
   1218 }
   1219 
   1220 // SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device.
   1221 func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {
   1222 	str16, err := UTF16FromString(str)
   1223 	if err != nil {
   1224 		return err
   1225 	}
   1226 	err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
   1227 	runtime.KeepAlive(str16)
   1228 	return err
   1229 }
   1230 
   1231 //sys	setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
   1232 
   1233 // SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
   1234 func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) {
   1235 	params := &DevInstallParams{}
   1236 	params.size = uint32(unsafe.Sizeof(*params))
   1237 
   1238 	return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params)
   1239 }
   1240 
   1241 // DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element.
   1242 func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) {
   1243 	return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData)
   1244 }
   1245 
   1246 //sys	setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW
   1247 
   1248 // SetupDiGetDeviceInstanceId function retrieves the instance ID of the device.
   1249 func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) {
   1250 	reqSize := uint32(1024)
   1251 	for {
   1252 		buf := make([]uint16, reqSize)
   1253 		err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize)
   1254 		if err == ERROR_INSUFFICIENT_BUFFER {
   1255 			continue
   1256 		}
   1257 		if err != nil {
   1258 			return "", err
   1259 		}
   1260 		return UTF16ToString(buf), nil
   1261 	}
   1262 }
   1263 
   1264 // DeviceInstanceID method retrieves the instance ID of the device.
   1265 func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) {
   1266 	return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData)
   1267 }
   1268 
   1269 // SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element.
   1270 //sys	SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW
   1271 
   1272 // ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element.
   1273 func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error {
   1274 	return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize)
   1275 }
   1276 
   1277 //sys	SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW
   1278 
   1279 // SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element.
   1280 func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error {
   1281 	return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams)
   1282 }
   1283 
   1284 // SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element.
   1285 //sys	SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW
   1286 
   1287 // SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element.
   1288 func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error {
   1289 	return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize)
   1290 }
   1291 
   1292 //sys	setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW
   1293 
   1294 // SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer.
   1295 func SetupDiClassNameFromGuidEx(classGUID *GUID, machineName string) (className string, err error) {
   1296 	var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16
   1297 
   1298 	var machineNameUTF16 *uint16
   1299 	if machineName != "" {
   1300 		machineNameUTF16, err = UTF16PtrFromString(machineName)
   1301 		if err != nil {
   1302 			return
   1303 		}
   1304 	}
   1305 
   1306 	err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0)
   1307 	if err != nil {
   1308 		return
   1309 	}
   1310 
   1311 	className = UTF16ToString(classNameUTF16[:])
   1312 	return
   1313 }
   1314 
   1315 //sys	setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW
   1316 
   1317 // 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.
   1318 func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]GUID, error) {
   1319 	classNameUTF16, err := UTF16PtrFromString(className)
   1320 	if err != nil {
   1321 		return nil, err
   1322 	}
   1323 
   1324 	var machineNameUTF16 *uint16
   1325 	if machineName != "" {
   1326 		machineNameUTF16, err = UTF16PtrFromString(machineName)
   1327 		if err != nil {
   1328 			return nil, err
   1329 		}
   1330 	}
   1331 
   1332 	reqSize := uint32(4)
   1333 	for {
   1334 		buf := make([]GUID, reqSize)
   1335 		err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)
   1336 		if err == ERROR_INSUFFICIENT_BUFFER {
   1337 			continue
   1338 		}
   1339 		if err != nil {
   1340 			return nil, err
   1341 		}
   1342 		return buf[:reqSize], nil
   1343 	}
   1344 }
   1345 
   1346 //sys	setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice
   1347 
   1348 // SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set.
   1349 func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) {
   1350 	data := &DevInfoData{}
   1351 	data.size = uint32(unsafe.Sizeof(*data))
   1352 
   1353 	return data, setupDiGetSelectedDevice(deviceInfoSet, data)
   1354 }
   1355 
   1356 // SelectedDevice method retrieves the selected device information element in a device information set.
   1357 func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) {
   1358 	return SetupDiGetSelectedDevice(deviceInfoSet)
   1359 }
   1360 
   1361 // 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.
   1362 //sys	SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice
   1363 
   1364 // 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.
   1365 func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error {
   1366 	return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData)
   1367 }
   1368 
   1369 //sys	setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) = setupapi.SetupUninstallOEMInfW
   1370 
   1371 // SetupUninstallOEMInf uninstalls the specified driver.
   1372 func SetupUninstallOEMInf(infFileName string, flags SUOI) error {
   1373 	infFileName16, err := UTF16PtrFromString(infFileName)
   1374 	if err != nil {
   1375 		return err
   1376 	}
   1377 	return setupUninstallOEMInf(infFileName16, flags, 0)
   1378 }
   1379 
   1380 //sys cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) = CfgMgr32.CM_MapCrToWin32Err
   1381 
   1382 //sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_List_SizeW
   1383 //sys cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_ListW
   1384 
   1385 func CM_Get_Device_Interface_List(deviceID string, interfaceClass *GUID, flags uint32) ([]string, error) {
   1386 	deviceID16, err := UTF16PtrFromString(deviceID)
   1387 	if err != nil {
   1388 		return nil, err
   1389 	}
   1390 	var buf []uint16
   1391 	var buflen uint32
   1392 	for {
   1393 		if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS {
   1394 			return nil, ret
   1395 		}
   1396 		buf = make([]uint16, buflen)
   1397 		if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS {
   1398 			break
   1399 		} else if ret != CR_BUFFER_SMALL {
   1400 			return nil, ret
   1401 		}
   1402 	}
   1403 	var interfaces []string
   1404 	for i := 0; i < len(buf); {
   1405 		j := i + wcslen(buf[i:])
   1406 		if i < j {
   1407 			interfaces = append(interfaces, UTF16ToString(buf[i:j]))
   1408 		}
   1409 		i = j + 1
   1410 	}
   1411 	if interfaces == nil {
   1412 		return nil, ERROR_NO_SUCH_DEVICE_INTERFACE
   1413 	}
   1414 	return interfaces, nil
   1415 }
   1416 
   1417 //sys cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_DevNode_Status
   1418 
   1419 func CM_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) error {
   1420 	ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags)
   1421 	if ret == CR_SUCCESS {
   1422 		return nil
   1423 	}
   1424 	return ret
   1425 }