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