github.com/tristanisham/sys@v0.0.0-20240326010300-a16cbabb7555/windows/setupapi_windows.go (about)

     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  }