setupapi_windows.go raw

   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  }
1426