Path: blob/main/vendor/golang.org/x/sys/windows/setupapi_windows.go
2880 views
// Copyright 2021 The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34package windows56import (7"encoding/binary"8"errors"9"fmt"10"runtime"11"strings"12"syscall"13"unsafe"14)1516// This file contains functions that wrap SetupAPI.dll and CfgMgr32.dll,17// core system functions for managing hardware devices, drivers, and the PnP tree.18// Information about these APIs can be found at:19// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi20// https://docs.microsoft.com/en-us/windows/win32/devinst/cfgmgr32-2122const (23ERROR_EXPECTED_SECTION_NAME Errno = 0x20000000 | 0xC0000000 | 024ERROR_BAD_SECTION_NAME_LINE Errno = 0x20000000 | 0xC0000000 | 125ERROR_SECTION_NAME_TOO_LONG Errno = 0x20000000 | 0xC0000000 | 226ERROR_GENERAL_SYNTAX Errno = 0x20000000 | 0xC0000000 | 327ERROR_WRONG_INF_STYLE Errno = 0x20000000 | 0xC0000000 | 0x10028ERROR_SECTION_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x10129ERROR_LINE_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x10230ERROR_NO_BACKUP Errno = 0x20000000 | 0xC0000000 | 0x10331ERROR_NO_ASSOCIATED_CLASS Errno = 0x20000000 | 0xC0000000 | 0x20032ERROR_CLASS_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x20133ERROR_DUPLICATE_FOUND Errno = 0x20000000 | 0xC0000000 | 0x20234ERROR_NO_DRIVER_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x20335ERROR_KEY_DOES_NOT_EXIST Errno = 0x20000000 | 0xC0000000 | 0x20436ERROR_INVALID_DEVINST_NAME Errno = 0x20000000 | 0xC0000000 | 0x20537ERROR_INVALID_CLASS Errno = 0x20000000 | 0xC0000000 | 0x20638ERROR_DEVINST_ALREADY_EXISTS Errno = 0x20000000 | 0xC0000000 | 0x20739ERROR_DEVINFO_NOT_REGISTERED Errno = 0x20000000 | 0xC0000000 | 0x20840ERROR_INVALID_REG_PROPERTY Errno = 0x20000000 | 0xC0000000 | 0x20941ERROR_NO_INF Errno = 0x20000000 | 0xC0000000 | 0x20A42ERROR_NO_SUCH_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x20B43ERROR_CANT_LOAD_CLASS_ICON Errno = 0x20000000 | 0xC0000000 | 0x20C44ERROR_INVALID_CLASS_INSTALLER Errno = 0x20000000 | 0xC0000000 | 0x20D45ERROR_DI_DO_DEFAULT Errno = 0x20000000 | 0xC0000000 | 0x20E46ERROR_DI_NOFILECOPY Errno = 0x20000000 | 0xC0000000 | 0x20F47ERROR_INVALID_HWPROFILE Errno = 0x20000000 | 0xC0000000 | 0x21048ERROR_NO_DEVICE_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x21149ERROR_DEVINFO_LIST_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x21250ERROR_DEVINFO_DATA_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x21351ERROR_DI_BAD_PATH Errno = 0x20000000 | 0xC0000000 | 0x21452ERROR_NO_CLASSINSTALL_PARAMS Errno = 0x20000000 | 0xC0000000 | 0x21553ERROR_FILEQUEUE_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x21654ERROR_BAD_SERVICE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x21755ERROR_NO_CLASS_DRIVER_LIST Errno = 0x20000000 | 0xC0000000 | 0x21856ERROR_NO_ASSOCIATED_SERVICE Errno = 0x20000000 | 0xC0000000 | 0x21957ERROR_NO_DEFAULT_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x21A58ERROR_DEVICE_INTERFACE_ACTIVE Errno = 0x20000000 | 0xC0000000 | 0x21B59ERROR_DEVICE_INTERFACE_REMOVED Errno = 0x20000000 | 0xC0000000 | 0x21C60ERROR_BAD_INTERFACE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x21D61ERROR_NO_SUCH_INTERFACE_CLASS Errno = 0x20000000 | 0xC0000000 | 0x21E62ERROR_INVALID_REFERENCE_STRING Errno = 0x20000000 | 0xC0000000 | 0x21F63ERROR_INVALID_MACHINENAME Errno = 0x20000000 | 0xC0000000 | 0x22064ERROR_REMOTE_COMM_FAILURE Errno = 0x20000000 | 0xC0000000 | 0x22165ERROR_MACHINE_UNAVAILABLE Errno = 0x20000000 | 0xC0000000 | 0x22266ERROR_NO_CONFIGMGR_SERVICES Errno = 0x20000000 | 0xC0000000 | 0x22367ERROR_INVALID_PROPPAGE_PROVIDER Errno = 0x20000000 | 0xC0000000 | 0x22468ERROR_NO_SUCH_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x22569ERROR_DI_POSTPROCESSING_REQUIRED Errno = 0x20000000 | 0xC0000000 | 0x22670ERROR_INVALID_COINSTALLER Errno = 0x20000000 | 0xC0000000 | 0x22771ERROR_NO_COMPAT_DRIVERS Errno = 0x20000000 | 0xC0000000 | 0x22872ERROR_NO_DEVICE_ICON Errno = 0x20000000 | 0xC0000000 | 0x22973ERROR_INVALID_INF_LOGCONFIG Errno = 0x20000000 | 0xC0000000 | 0x22A74ERROR_DI_DONT_INSTALL Errno = 0x20000000 | 0xC0000000 | 0x22B75ERROR_INVALID_FILTER_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22C76ERROR_NON_WINDOWS_NT_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22D77ERROR_NON_WINDOWS_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22E78ERROR_NO_CATALOG_FOR_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x22F79ERROR_DEVINSTALL_QUEUE_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x23080ERROR_NOT_DISABLEABLE Errno = 0x20000000 | 0xC0000000 | 0x23181ERROR_CANT_REMOVE_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x23282ERROR_INVALID_TARGET Errno = 0x20000000 | 0xC0000000 | 0x23383ERROR_DRIVER_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x23484ERROR_IN_WOW64 Errno = 0x20000000 | 0xC0000000 | 0x23585ERROR_SET_SYSTEM_RESTORE_POINT Errno = 0x20000000 | 0xC0000000 | 0x23686ERROR_SCE_DISABLED Errno = 0x20000000 | 0xC0000000 | 0x23887ERROR_UNKNOWN_EXCEPTION Errno = 0x20000000 | 0xC0000000 | 0x23988ERROR_PNP_REGISTRY_ERROR Errno = 0x20000000 | 0xC0000000 | 0x23A89ERROR_REMOTE_REQUEST_UNSUPPORTED Errno = 0x20000000 | 0xC0000000 | 0x23B90ERROR_NOT_AN_INSTALLED_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x23C91ERROR_INF_IN_USE_BY_DEVICES Errno = 0x20000000 | 0xC0000000 | 0x23D92ERROR_DI_FUNCTION_OBSOLETE Errno = 0x20000000 | 0xC0000000 | 0x23E93ERROR_NO_AUTHENTICODE_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x23F94ERROR_AUTHENTICODE_DISALLOWED Errno = 0x20000000 | 0xC0000000 | 0x24095ERROR_AUTHENTICODE_TRUSTED_PUBLISHER Errno = 0x20000000 | 0xC0000000 | 0x24196ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED Errno = 0x20000000 | 0xC0000000 | 0x24297ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED Errno = 0x20000000 | 0xC0000000 | 0x24398ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x24499ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE Errno = 0x20000000 | 0xC0000000 | 0x245100ERROR_DEVICE_INSTALLER_NOT_READY Errno = 0x20000000 | 0xC0000000 | 0x246101ERROR_DRIVER_STORE_ADD_FAILED Errno = 0x20000000 | 0xC0000000 | 0x247102ERROR_DEVICE_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x248103ERROR_DRIVER_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x249104ERROR_WRONG_INF_TYPE Errno = 0x20000000 | 0xC0000000 | 0x24A105ERROR_FILE_HASH_NOT_IN_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x24B106ERROR_DRIVER_STORE_DELETE_FAILED Errno = 0x20000000 | 0xC0000000 | 0x24C107ERROR_UNRECOVERABLE_STACK_OVERFLOW Errno = 0x20000000 | 0xC0000000 | 0x300108EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW109ERROR_NO_DEFAULT_INTERFACE_DEVICE Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE110ERROR_INTERFACE_DEVICE_ACTIVE Errno = ERROR_DEVICE_INTERFACE_ACTIVE111ERROR_INTERFACE_DEVICE_REMOVED Errno = ERROR_DEVICE_INTERFACE_REMOVED112ERROR_NO_SUCH_INTERFACE_DEVICE Errno = ERROR_NO_SUCH_DEVICE_INTERFACE113)114115const (116MAX_DEVICE_ID_LEN = 200117MAX_DEVNODE_ID_LEN = MAX_DEVICE_ID_LEN118MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null119MAX_CLASS_NAME_LEN = 32120MAX_PROFILE_LEN = 80121MAX_CONFIG_VALUE = 9999122MAX_INSTANCE_VALUE = 9999123CONFIGMG_VERSION = 0x0400124)125126// Maximum string length constants127const (128LINE_LEN = 256 // Windows 9x-compatible maximum for displayable strings coming from a device INF.129MAX_INF_STRING_LENGTH = 4096 // Actual maximum size of an INF string (including string substitutions).130MAX_INF_SECTION_NAME_LENGTH = 255 // For Windows 9x compatibility, INF section names should be constrained to 32 characters.131MAX_TITLE_LEN = 60132MAX_INSTRUCTION_LEN = 256133MAX_LABEL_LEN = 30134MAX_SERVICE_NAME_LEN = 256135MAX_SUBTITLE_LEN = 256136)137138const (139// SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0").140SP_MAX_MACHINENAME_LENGTH = MAX_PATH + 3141)142143// HSPFILEQ is type for setup file queue144type HSPFILEQ uintptr145146// DevInfo holds reference to device information set147type DevInfo Handle148149// DEVINST is a handle usually recognized by cfgmgr32 APIs150type DEVINST uint32151152// DevInfoData is a device information structure (references a device instance that is a member of a device information set)153type DevInfoData struct {154size uint32155ClassGUID GUID156DevInst DEVINST157_ uintptr158}159160// DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass).161type DevInfoListDetailData struct {162size uint32 // Use unsafeSizeOf method163ClassGUID GUID164RemoteMachineHandle Handle165remoteMachineName [SP_MAX_MACHINENAME_LENGTH]uint16166}167168func (*DevInfoListDetailData) unsafeSizeOf() uint32 {169if unsafe.Sizeof(uintptr(0)) == 4 {170// Windows declares this with pshpack1.h171return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName))172}173return uint32(unsafe.Sizeof(DevInfoListDetailData{}))174}175176func (data *DevInfoListDetailData) RemoteMachineName() string {177return UTF16ToString(data.remoteMachineName[:])178}179180func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error {181str, err := UTF16FromString(remoteMachineName)182if err != nil {183return err184}185copy(data.remoteMachineName[:], str)186return nil187}188189// DI_FUNCTION is function type for device installer190type DI_FUNCTION uint32191192const (193DIF_SELECTDEVICE DI_FUNCTION = 0x00000001194DIF_INSTALLDEVICE DI_FUNCTION = 0x00000002195DIF_ASSIGNRESOURCES DI_FUNCTION = 0x00000003196DIF_PROPERTIES DI_FUNCTION = 0x00000004197DIF_REMOVE DI_FUNCTION = 0x00000005198DIF_FIRSTTIMESETUP DI_FUNCTION = 0x00000006199DIF_FOUNDDEVICE DI_FUNCTION = 0x00000007200DIF_SELECTCLASSDRIVERS DI_FUNCTION = 0x00000008201DIF_VALIDATECLASSDRIVERS DI_FUNCTION = 0x00000009202DIF_INSTALLCLASSDRIVERS DI_FUNCTION = 0x0000000A203DIF_CALCDISKSPACE DI_FUNCTION = 0x0000000B204DIF_DESTROYPRIVATEDATA DI_FUNCTION = 0x0000000C205DIF_VALIDATEDRIVER DI_FUNCTION = 0x0000000D206DIF_DETECT DI_FUNCTION = 0x0000000F207DIF_INSTALLWIZARD DI_FUNCTION = 0x00000010208DIF_DESTROYWIZARDDATA DI_FUNCTION = 0x00000011209DIF_PROPERTYCHANGE DI_FUNCTION = 0x00000012210DIF_ENABLECLASS DI_FUNCTION = 0x00000013211DIF_DETECTVERIFY DI_FUNCTION = 0x00000014212DIF_INSTALLDEVICEFILES DI_FUNCTION = 0x00000015213DIF_UNREMOVE DI_FUNCTION = 0x00000016214DIF_SELECTBESTCOMPATDRV DI_FUNCTION = 0x00000017215DIF_ALLOW_INSTALL DI_FUNCTION = 0x00000018216DIF_REGISTERDEVICE DI_FUNCTION = 0x00000019217DIF_NEWDEVICEWIZARD_PRESELECT DI_FUNCTION = 0x0000001A218DIF_NEWDEVICEWIZARD_SELECT DI_FUNCTION = 0x0000001B219DIF_NEWDEVICEWIZARD_PREANALYZE DI_FUNCTION = 0x0000001C220DIF_NEWDEVICEWIZARD_POSTANALYZE DI_FUNCTION = 0x0000001D221DIF_NEWDEVICEWIZARD_FINISHINSTALL DI_FUNCTION = 0x0000001E222DIF_INSTALLINTERFACES DI_FUNCTION = 0x00000020223DIF_DETECTCANCEL DI_FUNCTION = 0x00000021224DIF_REGISTER_COINSTALLERS DI_FUNCTION = 0x00000022225DIF_ADDPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000023226DIF_ADDPROPERTYPAGE_BASIC DI_FUNCTION = 0x00000024227DIF_TROUBLESHOOTER DI_FUNCTION = 0x00000026228DIF_POWERMESSAGEWAKE DI_FUNCTION = 0x00000027229DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028230DIF_UPDATEDRIVER_UI DI_FUNCTION = 0x00000029231DIF_FINISHINSTALL_ACTION DI_FUNCTION = 0x0000002A232)233234// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set)235type DevInstallParams struct {236size uint32237Flags DI_FLAGS238FlagsEx DI_FLAGSEX239hwndParent uintptr240InstallMsgHandler uintptr241InstallMsgHandlerContext uintptr242FileQueue HSPFILEQ243_ uintptr244_ uint32245driverPath [MAX_PATH]uint16246}247248func (params *DevInstallParams) DriverPath() string {249return UTF16ToString(params.driverPath[:])250}251252func (params *DevInstallParams) SetDriverPath(driverPath string) error {253str, err := UTF16FromString(driverPath)254if err != nil {255return err256}257copy(params.driverPath[:], str)258return nil259}260261// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values262type DI_FLAGS uint32263264const (265// Flags for choosing a device266DI_SHOWOEM DI_FLAGS = 0x00000001 // support Other... button267DI_SHOWCOMPAT DI_FLAGS = 0x00000002 // show compatibility list268DI_SHOWCLASS DI_FLAGS = 0x00000004 // show class list269DI_SHOWALL DI_FLAGS = 0x00000007 // both class & compat list shown270DI_NOVCP DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue271DI_DIDCOMPAT DI_FLAGS = 0x00000010 // Searched for compatible devices272DI_DIDCLASS DI_FLAGS = 0x00000020 // Searched for class devices273DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible274275// Flags returned by DiInstallDevice to indicate need to reboot/restart276DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect277DI_NEEDREBOOT DI_FLAGS = 0x00000100 // ""278279// Flags for device installation280DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk281282// Flags set by DiBuildDriverInfoList283DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list284285// Flag indicates that device is disabled286DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled287288// Flags for Device/Class Properties289DI_GENERALPAGE_ADDED DI_FLAGS = 0x00001000290DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000291292// Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated.293DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000294295// Flag to indicate that the sorting from the INF file should be used.296DI_INF_IS_SORTED DI_FLAGS = 0x00008000297298// Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.299DI_ENUMSINGLEINF DI_FLAGS = 0x00010000300301// Flag that prevents ConfigMgr from removing/re-enumerating devices during device302// registration, installation, and deletion.303DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000304305// The following flag can be used to install a device disabled306DI_INSTALLDISABLED DI_FLAGS = 0x00040000307308// Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver309// list from its existing class driver list, instead of the normal INF search.310DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000311312// This flag is set if the Class Install params should be used.313DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000314315// 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.316DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000317318// Flags for device installation319DI_QUIETINSTALL DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info320DI_NOFILECOPY DI_FLAGS = 0x01000000 // No file Copy necessary321DI_FORCECOPY DI_FLAGS = 0x02000000 // Force files to be copied from install path322DI_DRIVERPAGE_ADDED DI_FLAGS = 0x04000000 // Prop provider added Driver page.323DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg324DI_OVERRIDE_INFFLAGS DI_FLAGS = 0x10000000 // Override INF flags325DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props326327DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs328329DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install330)331332// DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values333type DI_FLAGSEX uint32334335const (336DI_FLAGSEX_CI_FAILED DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer337DI_FLAGSEX_FINISHINSTALL_ACTION DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context.338DI_FLAGSEX_DIDINFOLIST DI_FLAGSEX = 0x00000010 // Did the Class Info List339DI_FLAGSEX_DIDCOMPATINFO DI_FLAGSEX = 0x00000020 // Did the Compat Info List340DI_FLAGSEX_FILTERCLASSES DI_FLAGSEX = 0x00000040341DI_FLAGSEX_SETFAILEDINSTALL DI_FLAGSEX = 0x00000080342DI_FLAGSEX_DEVICECHANGE DI_FLAGSEX = 0x00000100343DI_FLAGSEX_ALWAYSWRITEIDS DI_FLAGSEX = 0x00000200344DI_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.345DI_FLAGSEX_ALLOWEXCLUDEDDRVS DI_FLAGSEX = 0x00000800346DI_FLAGSEX_NOUIONQUERYREMOVE DI_FLAGSEX = 0x00001000347DI_FLAGSEX_USECLASSFORCOMPAT DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.)348DI_FLAGSEX_NO_DRVREG_MODIFY DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key.349DI_FLAGSEX_IN_SYSTEM_SETUP DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup.350DI_FLAGSEX_INET_DRIVER DI_FLAGSEX = 0x00020000 // Driver came from Windows Update351DI_FLAGSEX_APPENDDRIVERLIST DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list.352DI_FLAGSEX_PREINSTALLBACKUP DI_FLAGSEX = 0x00080000 // not used353DI_FLAGSEX_BACKUPONREPLACE DI_FLAGSEX = 0x00100000 // not used354DI_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)355DI_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.356DI_FLAGSEX_POWERPAGE_ADDED DI_FLAGSEX = 0x01000000 // class installer added their own power page357DI_FLAGSEX_FILTERSIMILARDRIVERS DI_FLAGSEX = 0x02000000 // only include similar drivers in class list358DI_FLAGSEX_INSTALLEDDRIVER DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list. Used in calls to SetupDiBuildDriverInfoList359DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list360DI_FLAGSEX_ALTPLATFORM_DRVSEARCH DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue361DI_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.362DI_FLAGSEX_RECURSIVESEARCH DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search363DI_FLAGSEX_SEARCH_PUBLISHED_INFS DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search364)365366// 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.367type ClassInstallHeader struct {368size uint32369InstallFunction DI_FUNCTION370}371372func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader {373hdr := &ClassInstallHeader{InstallFunction: installFunction}374hdr.size = uint32(unsafe.Sizeof(*hdr))375return hdr376}377378// DICS_STATE specifies values indicating a change in a device's state379type DICS_STATE uint32380381const (382DICS_ENABLE DICS_STATE = 0x00000001 // The device is being enabled.383DICS_DISABLE DICS_STATE = 0x00000002 // The device is being disabled.384DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed.385DICS_START DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile).386DICS_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.387)388389// DICS_FLAG specifies the scope of a device property change390type DICS_FLAG uint32391392const (393DICS_FLAG_GLOBAL DICS_FLAG = 0x00000001 // make change in all hardware profiles394DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only395DICS_FLAG_CONFIGGENERAL DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete)396)397398// PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function.399type PropChangeParams struct {400ClassInstallHeader ClassInstallHeader401StateChange DICS_STATE402Scope DICS_FLAG403HwProfile uint32404}405406// DI_REMOVEDEVICE specifies the scope of the device removal407type DI_REMOVEDEVICE uint32408409const (410DI_REMOVEDEVICE_GLOBAL DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry.411DI_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.412)413414// RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function.415type RemoveDeviceParams struct {416ClassInstallHeader ClassInstallHeader417Scope DI_REMOVEDEVICE418HwProfile uint32419}420421// 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)422type DrvInfoData struct {423size uint32424DriverType uint32425_ uintptr426description [LINE_LEN]uint16427mfgName [LINE_LEN]uint16428providerName [LINE_LEN]uint16429DriverDate Filetime430DriverVersion uint64431}432433func (data *DrvInfoData) Description() string {434return UTF16ToString(data.description[:])435}436437func (data *DrvInfoData) SetDescription(description string) error {438str, err := UTF16FromString(description)439if err != nil {440return err441}442copy(data.description[:], str)443return nil444}445446func (data *DrvInfoData) MfgName() string {447return UTF16ToString(data.mfgName[:])448}449450func (data *DrvInfoData) SetMfgName(mfgName string) error {451str, err := UTF16FromString(mfgName)452if err != nil {453return err454}455copy(data.mfgName[:], str)456return nil457}458459func (data *DrvInfoData) ProviderName() string {460return UTF16ToString(data.providerName[:])461}462463func (data *DrvInfoData) SetProviderName(providerName string) error {464str, err := UTF16FromString(providerName)465if err != nil {466return err467}468copy(data.providerName[:], str)469return nil470}471472// IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters.473func (data *DrvInfoData) IsNewer(driverDate Filetime, driverVersion uint64) bool {474if data.DriverDate.HighDateTime > driverDate.HighDateTime {475return true476}477if data.DriverDate.HighDateTime < driverDate.HighDateTime {478return false479}480481if data.DriverDate.LowDateTime > driverDate.LowDateTime {482return true483}484if data.DriverDate.LowDateTime < driverDate.LowDateTime {485return false486}487488if data.DriverVersion > driverVersion {489return true490}491if data.DriverVersion < driverVersion {492return false493}494495return false496}497498// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure)499type DrvInfoDetailData struct {500size uint32 // Use unsafeSizeOf method501InfDate Filetime502compatIDsOffset uint32503compatIDsLength uint32504_ uintptr505sectionName [LINE_LEN]uint16506infFileName [MAX_PATH]uint16507drvDescription [LINE_LEN]uint16508hardwareID [1]uint16509}510511func (*DrvInfoDetailData) unsafeSizeOf() uint32 {512if unsafe.Sizeof(uintptr(0)) == 4 {513// Windows declares this with pshpack1.h514return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID))515}516return uint32(unsafe.Sizeof(DrvInfoDetailData{}))517}518519func (data *DrvInfoDetailData) SectionName() string {520return UTF16ToString(data.sectionName[:])521}522523func (data *DrvInfoDetailData) InfFileName() string {524return UTF16ToString(data.infFileName[:])525}526527func (data *DrvInfoDetailData) DrvDescription() string {528return UTF16ToString(data.drvDescription[:])529}530531func (data *DrvInfoDetailData) HardwareID() string {532if data.compatIDsOffset > 1 {533bufW := data.getBuf()534return UTF16ToString(bufW[:wcslen(bufW)])535}536537return ""538}539540func (data *DrvInfoDetailData) CompatIDs() []string {541a := make([]string, 0)542543if data.compatIDsLength > 0 {544bufW := data.getBuf()545bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength]546for i := 0; i < len(bufW); {547j := i + wcslen(bufW[i:])548if i < j {549a = append(a, UTF16ToString(bufW[i:j]))550}551i = j + 1552}553}554555return a556}557558func (data *DrvInfoDetailData) getBuf() []uint16 {559len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2560sl := struct {561addr *uint16562len int563cap int564}{&data.hardwareID[0], int(len), int(len)}565return *(*[]uint16)(unsafe.Pointer(&sl))566}567568// IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list.569func (data *DrvInfoDetailData) IsCompatible(hwid string) bool {570hwidLC := strings.ToLower(hwid)571if strings.ToLower(data.HardwareID()) == hwidLC {572return true573}574a := data.CompatIDs()575for i := range a {576if strings.ToLower(a[i]) == hwidLC {577return true578}579}580581return false582}583584// DICD flags control SetupDiCreateDeviceInfo585type DICD uint32586587const (588DICD_GENERATE_ID DICD = 0x00000001589DICD_INHERIT_CLASSDRVS DICD = 0x00000002590)591592// SUOI flags control SetupUninstallOEMInf593type SUOI uint32594595const (596SUOI_FORCEDELETE SUOI = 0x0001597)598599// SPDIT flags to distinguish between class drivers and600// device drivers. (Passed in 'DriverType' parameter of601// driver information list APIs)602type SPDIT uint32603604const (605SPDIT_NODRIVER SPDIT = 0x00000000606SPDIT_CLASSDRIVER SPDIT = 0x00000001607SPDIT_COMPATDRIVER SPDIT = 0x00000002608)609610// DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs611type DIGCF uint32612613const (614DIGCF_DEFAULT DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE615DIGCF_PRESENT DIGCF = 0x00000002616DIGCF_ALLCLASSES DIGCF = 0x00000004617DIGCF_PROFILE DIGCF = 0x00000008618DIGCF_DEVICEINTERFACE DIGCF = 0x00000010619)620621// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey.622type DIREG uint32623624const (625DIREG_DEV DIREG = 0x00000001 // Open/Create/Delete device key626DIREG_DRV DIREG = 0x00000002 // Open/Create/Delete driver key627DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key628)629630// SPDRP specifies device registry property codes631// (Codes marked as read-only (R) may only be used for632// SetupDiGetDeviceRegistryProperty)633//634// These values should cover the same set of registry properties635// as defined by the CM_DRP codes in cfgmgr32.h.636//637// Note that SPDRP codes are zero based while CM_DRP codes are one based!638type SPDRP uint32639640const (641SPDRP_DEVICEDESC SPDRP = 0x00000000 // DeviceDesc (R/W)642SPDRP_HARDWAREID SPDRP = 0x00000001 // HardwareID (R/W)643SPDRP_COMPATIBLEIDS SPDRP = 0x00000002 // CompatibleIDs (R/W)644SPDRP_SERVICE SPDRP = 0x00000004 // Service (R/W)645SPDRP_CLASS SPDRP = 0x00000007 // Class (R--tied to ClassGUID)646SPDRP_CLASSGUID SPDRP = 0x00000008 // ClassGUID (R/W)647SPDRP_DRIVER SPDRP = 0x00000009 // Driver (R/W)648SPDRP_CONFIGFLAGS SPDRP = 0x0000000A // ConfigFlags (R/W)649SPDRP_MFG SPDRP = 0x0000000B // Mfg (R/W)650SPDRP_FRIENDLYNAME SPDRP = 0x0000000C // FriendlyName (R/W)651SPDRP_LOCATION_INFORMATION SPDRP = 0x0000000D // LocationInformation (R/W)652SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R)653SPDRP_CAPABILITIES SPDRP = 0x0000000F // Capabilities (R)654SPDRP_UI_NUMBER SPDRP = 0x00000010 // UiNumber (R)655SPDRP_UPPERFILTERS SPDRP = 0x00000011 // UpperFilters (R/W)656SPDRP_LOWERFILTERS SPDRP = 0x00000012 // LowerFilters (R/W)657SPDRP_BUSTYPEGUID SPDRP = 0x00000013 // BusTypeGUID (R)658SPDRP_LEGACYBUSTYPE SPDRP = 0x00000014 // LegacyBusType (R)659SPDRP_BUSNUMBER SPDRP = 0x00000015 // BusNumber (R)660SPDRP_ENUMERATOR_NAME SPDRP = 0x00000016 // Enumerator Name (R)661SPDRP_SECURITY SPDRP = 0x00000017 // Security (R/W, binary form)662SPDRP_SECURITY_SDS SPDRP = 0x00000018 // Security (W, SDS form)663SPDRP_DEVTYPE SPDRP = 0x00000019 // Device Type (R/W)664SPDRP_EXCLUSIVE SPDRP = 0x0000001A // Device is exclusive-access (R/W)665SPDRP_CHARACTERISTICS SPDRP = 0x0000001B // Device Characteristics (R/W)666SPDRP_ADDRESS SPDRP = 0x0000001C // Device Address (R)667SPDRP_UI_NUMBER_DESC_FORMAT SPDRP = 0x0000001D // UiNumberDescFormat (R/W)668SPDRP_DEVICE_POWER_DATA SPDRP = 0x0000001E // Device Power Data (R)669SPDRP_REMOVAL_POLICY SPDRP = 0x0000001F // Removal Policy (R)670SPDRP_REMOVAL_POLICY_HW_DEFAULT SPDRP = 0x00000020 // Hardware Removal Policy (R)671SPDRP_REMOVAL_POLICY_OVERRIDE SPDRP = 0x00000021 // Removal Policy Override (RW)672SPDRP_INSTALL_STATE SPDRP = 0x00000022 // Device Install State (R)673SPDRP_LOCATION_PATHS SPDRP = 0x00000023 // Device Location Paths (R)674SPDRP_BASE_CONTAINERID SPDRP = 0x00000024 // Base ContainerID (R)675676SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals677)678679// DEVPROPTYPE represents the property-data-type identifier that specifies the680// data type of a device property value in the unified device property model.681type DEVPROPTYPE uint32682683const (684DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000685DEVPROP_TYPEMOD_LIST DEVPROPTYPE = 0x00002000686687DEVPROP_TYPE_EMPTY DEVPROPTYPE = 0x00000000688DEVPROP_TYPE_NULL DEVPROPTYPE = 0x00000001689DEVPROP_TYPE_SBYTE DEVPROPTYPE = 0x00000002690DEVPROP_TYPE_BYTE DEVPROPTYPE = 0x00000003691DEVPROP_TYPE_INT16 DEVPROPTYPE = 0x00000004692DEVPROP_TYPE_UINT16 DEVPROPTYPE = 0x00000005693DEVPROP_TYPE_INT32 DEVPROPTYPE = 0x00000006694DEVPROP_TYPE_UINT32 DEVPROPTYPE = 0x00000007695DEVPROP_TYPE_INT64 DEVPROPTYPE = 0x00000008696DEVPROP_TYPE_UINT64 DEVPROPTYPE = 0x00000009697DEVPROP_TYPE_FLOAT DEVPROPTYPE = 0x0000000A698DEVPROP_TYPE_DOUBLE DEVPROPTYPE = 0x0000000B699DEVPROP_TYPE_DECIMAL DEVPROPTYPE = 0x0000000C700DEVPROP_TYPE_GUID DEVPROPTYPE = 0x0000000D701DEVPROP_TYPE_CURRENCY DEVPROPTYPE = 0x0000000E702DEVPROP_TYPE_DATE DEVPROPTYPE = 0x0000000F703DEVPROP_TYPE_FILETIME DEVPROPTYPE = 0x00000010704DEVPROP_TYPE_BOOLEAN DEVPROPTYPE = 0x00000011705DEVPROP_TYPE_STRING DEVPROPTYPE = 0x00000012706DEVPROP_TYPE_STRING_LIST DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST707DEVPROP_TYPE_SECURITY_DESCRIPTOR DEVPROPTYPE = 0x00000013708DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014709DEVPROP_TYPE_DEVPROPKEY DEVPROPTYPE = 0x00000015710DEVPROP_TYPE_DEVPROPTYPE DEVPROPTYPE = 0x00000016711DEVPROP_TYPE_BINARY DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY712DEVPROP_TYPE_ERROR DEVPROPTYPE = 0x00000017713DEVPROP_TYPE_NTSTATUS DEVPROPTYPE = 0x00000018714DEVPROP_TYPE_STRING_INDIRECT DEVPROPTYPE = 0x00000019715716MAX_DEVPROP_TYPE DEVPROPTYPE = 0x00000019717MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000718719DEVPROP_MASK_TYPE DEVPROPTYPE = 0x00000FFF720DEVPROP_MASK_TYPEMOD DEVPROPTYPE = 0x0000F000721)722723// DEVPROPGUID specifies a property category.724type DEVPROPGUID GUID725726// DEVPROPID uniquely identifies the property within the property category.727type DEVPROPID uint32728729const DEVPROPID_FIRST_USABLE DEVPROPID = 2730731// DEVPROPKEY represents a device property key for a device property in the732// unified device property model.733type DEVPROPKEY struct {734FmtID DEVPROPGUID735PID DEVPROPID736}737738// CONFIGRET is a return value or error code from cfgmgr32 APIs739type CONFIGRET uint32740741func (ret CONFIGRET) Error() string {742if win32Error, ok := ret.Unwrap().(Errno); ok {743return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret))744}745return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret))746}747748func (ret CONFIGRET) Win32Error(defaultError Errno) Errno {749return cm_MapCrToWin32Err(ret, defaultError)750}751752func (ret CONFIGRET) Unwrap() error {753const noMatch = Errno(^uintptr(0))754win32Error := ret.Win32Error(noMatch)755if win32Error == noMatch {756return nil757}758return win32Error759}760761const (762CR_SUCCESS CONFIGRET = 0x00000000763CR_DEFAULT CONFIGRET = 0x00000001764CR_OUT_OF_MEMORY CONFIGRET = 0x00000002765CR_INVALID_POINTER CONFIGRET = 0x00000003766CR_INVALID_FLAG CONFIGRET = 0x00000004767CR_INVALID_DEVNODE CONFIGRET = 0x00000005768CR_INVALID_DEVINST = CR_INVALID_DEVNODE769CR_INVALID_RES_DES CONFIGRET = 0x00000006770CR_INVALID_LOG_CONF CONFIGRET = 0x00000007771CR_INVALID_ARBITRATOR CONFIGRET = 0x00000008772CR_INVALID_NODELIST CONFIGRET = 0x00000009773CR_DEVNODE_HAS_REQS CONFIGRET = 0x0000000A774CR_DEVINST_HAS_REQS = CR_DEVNODE_HAS_REQS775CR_INVALID_RESOURCEID CONFIGRET = 0x0000000B776CR_DLVXD_NOT_FOUND CONFIGRET = 0x0000000C777CR_NO_SUCH_DEVNODE CONFIGRET = 0x0000000D778CR_NO_SUCH_DEVINST = CR_NO_SUCH_DEVNODE779CR_NO_MORE_LOG_CONF CONFIGRET = 0x0000000E780CR_NO_MORE_RES_DES CONFIGRET = 0x0000000F781CR_ALREADY_SUCH_DEVNODE CONFIGRET = 0x00000010782CR_ALREADY_SUCH_DEVINST = CR_ALREADY_SUCH_DEVNODE783CR_INVALID_RANGE_LIST CONFIGRET = 0x00000011784CR_INVALID_RANGE CONFIGRET = 0x00000012785CR_FAILURE CONFIGRET = 0x00000013786CR_NO_SUCH_LOGICAL_DEV CONFIGRET = 0x00000014787CR_CREATE_BLOCKED CONFIGRET = 0x00000015788CR_NOT_SYSTEM_VM CONFIGRET = 0x00000016789CR_REMOVE_VETOED CONFIGRET = 0x00000017790CR_APM_VETOED CONFIGRET = 0x00000018791CR_INVALID_LOAD_TYPE CONFIGRET = 0x00000019792CR_BUFFER_SMALL CONFIGRET = 0x0000001A793CR_NO_ARBITRATOR CONFIGRET = 0x0000001B794CR_NO_REGISTRY_HANDLE CONFIGRET = 0x0000001C795CR_REGISTRY_ERROR CONFIGRET = 0x0000001D796CR_INVALID_DEVICE_ID CONFIGRET = 0x0000001E797CR_INVALID_DATA CONFIGRET = 0x0000001F798CR_INVALID_API CONFIGRET = 0x00000020799CR_DEVLOADER_NOT_READY CONFIGRET = 0x00000021800CR_NEED_RESTART CONFIGRET = 0x00000022801CR_NO_MORE_HW_PROFILES CONFIGRET = 0x00000023802CR_DEVICE_NOT_THERE CONFIGRET = 0x00000024803CR_NO_SUCH_VALUE CONFIGRET = 0x00000025804CR_WRONG_TYPE CONFIGRET = 0x00000026805CR_INVALID_PRIORITY CONFIGRET = 0x00000027806CR_NOT_DISABLEABLE CONFIGRET = 0x00000028807CR_FREE_RESOURCES CONFIGRET = 0x00000029808CR_QUERY_VETOED CONFIGRET = 0x0000002A809CR_CANT_SHARE_IRQ CONFIGRET = 0x0000002B810CR_NO_DEPENDENT CONFIGRET = 0x0000002C811CR_SAME_RESOURCES CONFIGRET = 0x0000002D812CR_NO_SUCH_REGISTRY_KEY CONFIGRET = 0x0000002E813CR_INVALID_MACHINENAME CONFIGRET = 0x0000002F814CR_REMOTE_COMM_FAILURE CONFIGRET = 0x00000030815CR_MACHINE_UNAVAILABLE CONFIGRET = 0x00000031816CR_NO_CM_SERVICES CONFIGRET = 0x00000032817CR_ACCESS_DENIED CONFIGRET = 0x00000033818CR_CALL_NOT_IMPLEMENTED CONFIGRET = 0x00000034819CR_INVALID_PROPERTY CONFIGRET = 0x00000035820CR_DEVICE_INTERFACE_ACTIVE CONFIGRET = 0x00000036821CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037822CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038823CR_INVALID_CONFLICT_LIST CONFIGRET = 0x00000039824CR_INVALID_INDEX CONFIGRET = 0x0000003A825CR_INVALID_STRUCTURE_SIZE CONFIGRET = 0x0000003B826NUM_CR_RESULTS CONFIGRET = 0x0000003C827)828829const (830CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0 // only currently 'live' device interfaces831CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not832)833834const (835DN_ROOT_ENUMERATED = 0x00000001 // Was enumerated by ROOT836DN_DRIVER_LOADED = 0x00000002 // Has Register_Device_Driver837DN_ENUM_LOADED = 0x00000004 // Has Register_Enumerator838DN_STARTED = 0x00000008 // Is currently configured839DN_MANUAL = 0x00000010 // Manually installed840DN_NEED_TO_ENUM = 0x00000020 // May need reenumeration841DN_NOT_FIRST_TIME = 0x00000040 // Has received a config842DN_HARDWARE_ENUM = 0x00000080 // Enum generates hardware ID843DN_LIAR = 0x00000100 // Lied about can reconfig once844DN_HAS_MARK = 0x00000200 // Not CM_Create_DevInst lately845DN_HAS_PROBLEM = 0x00000400 // Need device installer846DN_FILTERED = 0x00000800 // Is filtered847DN_MOVED = 0x00001000 // Has been moved848DN_DISABLEABLE = 0x00002000 // Can be disabled849DN_REMOVABLE = 0x00004000 // Can be removed850DN_PRIVATE_PROBLEM = 0x00008000 // Has a private problem851DN_MF_PARENT = 0x00010000 // Multi function parent852DN_MF_CHILD = 0x00020000 // Multi function child853DN_WILL_BE_REMOVED = 0x00040000 // DevInst is being removed854DN_NOT_FIRST_TIMEE = 0x00080000 // Has received a config enumerate855DN_STOP_FREE_RES = 0x00100000 // When child is stopped, free resources856DN_REBAL_CANDIDATE = 0x00200000 // Don't skip during rebalance857DN_BAD_PARTIAL = 0x00400000 // This devnode's log_confs do not have same resources858DN_NT_ENUMERATOR = 0x00800000 // This devnode's is an NT enumerator859DN_NT_DRIVER = 0x01000000 // This devnode's is an NT driver860DN_NEEDS_LOCKING = 0x02000000 // Devnode need lock resume processing861DN_ARM_WAKEUP = 0x04000000 // Devnode can be the wakeup device862DN_APM_ENUMERATOR = 0x08000000 // APM aware enumerator863DN_APM_DRIVER = 0x10000000 // APM aware driver864DN_SILENT_INSTALL = 0x20000000 // Silent install865DN_NO_SHOW_IN_DM = 0x40000000 // No show in device manager866DN_BOOT_LOG_PROB = 0x80000000 // Had a problem during preassignment of boot log conf867DN_NEED_RESTART = DN_LIAR // System needs to be restarted for this Devnode to work properly868DN_DRIVER_BLOCKED = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode869DN_LEGACY_DRIVER = DN_MOVED // This device is using a legacy driver870DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK // One or more children have invalid IDs871DN_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.872DN_QUERY_REMOVE_PENDING = DN_MF_PARENT // Device is part of a set of related devices collectively pending query-removal873DN_QUERY_REMOVE_ACTIVE = DN_MF_CHILD // Device is actively engaged in a query-remove IRP874DN_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_DM875)876877//sys setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW878879// 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.880func SetupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) {881var machineNameUTF16 *uint16882if machineName != "" {883machineNameUTF16, err = UTF16PtrFromString(machineName)884if err != nil {885return886}887}888return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0)889}890891//sys setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW892893// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.894func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) {895data := &DevInfoListDetailData{}896data.size = data.unsafeSizeOf()897898return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data)899}900901// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.902func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) {903return SetupDiGetDeviceInfoListDetail(deviceInfoSet)904}905906//sys setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW907908// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set.909func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) {910deviceNameUTF16, err := UTF16PtrFromString(deviceName)911if err != nil {912return913}914915var deviceDescriptionUTF16 *uint16916if deviceDescription != "" {917deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription)918if err != nil {919return920}921}922923data := &DevInfoData{}924data.size = uint32(unsafe.Sizeof(*data))925926return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data)927}928929// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set.930func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) {931return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags)932}933934//sys setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo935936// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set.937func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) {938data := &DevInfoData{}939data.size = uint32(unsafe.Sizeof(*data))940941return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data)942}943944// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set.945func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) {946return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex)947}948949// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.950//sys SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList951952// Close method deletes a device information set and frees all associated memory.953func (deviceInfoSet DevInfo) Close() error {954return SetupDiDestroyDeviceInfoList(deviceInfoSet)955}956957//sys SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList958959// 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.960func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {961return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType)962}963964//sys SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch965966// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread.967func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error {968return SetupDiCancelDriverInfoSearch(deviceInfoSet)969}970971//sys setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW972973// SetupDiEnumDriverInfo function enumerates the members of a driver list.974func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {975data := &DrvInfoData{}976data.size = uint32(unsafe.Sizeof(*data))977978return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data)979}980981// EnumDriverInfo method enumerates the members of a driver list.982func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {983return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex)984}985986//sys setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW987988// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element.989func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) {990data := &DrvInfoData{}991data.size = uint32(unsafe.Sizeof(*data))992993return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data)994}995996// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element.997func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) {998return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData)999}10001001//sys SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW10021003// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.1004func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error {1005return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData)1006}10071008//sys setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW10091010// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.1011func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {1012reqSize := uint32(2048)1013for {1014buf := make([]byte, reqSize)1015data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))1016data.size = data.unsafeSizeOf()1017err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)1018if err == ERROR_INSUFFICIENT_BUFFER {1019continue1020}1021if err != nil {1022return nil, err1023}1024data.size = reqSize1025return data, nil1026}1027}10281029// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set.1030func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {1031return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData)1032}10331034//sys SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList10351036// DestroyDriverInfoList method deletes a driver list.1037func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {1038return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType)1039}10401041//sys setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiGetClassDevsExW10421043// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer.1044func SetupDiGetClassDevsEx(classGUID *GUID, enumerator string, hwndParent uintptr, flags DIGCF, deviceInfoSet DevInfo, machineName string) (handle DevInfo, err error) {1045var enumeratorUTF16 *uint161046if enumerator != "" {1047enumeratorUTF16, err = UTF16PtrFromString(enumerator)1048if err != nil {1049return1050}1051}1052var machineNameUTF16 *uint161053if machineName != "" {1054machineNameUTF16, err = UTF16PtrFromString(machineName)1055if err != nil {1056return1057}1058}1059return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0)1060}10611062// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).1063//sys SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller10641065// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).1066func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error {1067return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData)1068}10691070// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.1071//sys SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) [failretval==InvalidHandle] = setupapi.SetupDiOpenDevRegKey10721073// OpenDevRegKey method opens a registry key for device-specific configuration information.1074func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (Handle, error) {1075return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired)1076}10771078//sys setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) = setupapi.SetupDiGetDevicePropertyW10791080// SetupDiGetDeviceProperty function retrieves a specified device instance property.1081func SetupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY) (value interface{}, err error) {1082reqSize := uint32(256)1083for {1084var dataType DEVPROPTYPE1085buf := make([]byte, reqSize)1086err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0)1087if err == ERROR_INSUFFICIENT_BUFFER {1088continue1089}1090if err != nil {1091return1092}1093switch dataType {1094case DEVPROP_TYPE_STRING:1095ret := UTF16ToString(bufToUTF16(buf))1096runtime.KeepAlive(buf)1097return ret, nil1098}1099return nil, errors.New("unimplemented property type")1100}1101}11021103//sys setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW11041105// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property.1106func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) {1107reqSize := uint32(256)1108for {1109var dataType uint321110buf := make([]byte, reqSize)1111err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)1112if err == ERROR_INSUFFICIENT_BUFFER {1113continue1114}1115if err != nil {1116return1117}1118return getRegistryValue(buf[:reqSize], dataType)1119}1120}11211122func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {1123switch dataType {1124case REG_SZ:1125ret := UTF16ToString(bufToUTF16(buf))1126runtime.KeepAlive(buf)1127return ret, nil1128case REG_EXPAND_SZ:1129value := UTF16ToString(bufToUTF16(buf))1130if value == "" {1131return "", nil1132}1133p, err := syscall.UTF16PtrFromString(value)1134if err != nil {1135return "", err1136}1137ret := make([]uint16, 100)1138for {1139n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret)))1140if err != nil {1141return "", err1142}1143if n <= uint32(len(ret)) {1144return UTF16ToString(ret[:n]), nil1145}1146ret = make([]uint16, n)1147}1148case REG_BINARY:1149return buf, nil1150case REG_DWORD_LITTLE_ENDIAN:1151return binary.LittleEndian.Uint32(buf), nil1152case REG_DWORD_BIG_ENDIAN:1153return binary.BigEndian.Uint32(buf), nil1154case REG_MULTI_SZ:1155bufW := bufToUTF16(buf)1156a := []string{}1157for i := 0; i < len(bufW); {1158j := i + wcslen(bufW[i:])1159if i < j {1160a = append(a, UTF16ToString(bufW[i:j]))1161}1162i = j + 11163}1164runtime.KeepAlive(buf)1165return a, nil1166case REG_QWORD_LITTLE_ENDIAN:1167return binary.LittleEndian.Uint64(buf), nil1168default:1169return nil, fmt.Errorf("Unsupported registry value type: %v", dataType)1170}1171}11721173// bufToUTF16 function reinterprets []byte buffer as []uint161174func bufToUTF16(buf []byte) []uint16 {1175sl := struct {1176addr *uint161177len int1178cap int1179}{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2}1180return *(*[]uint16)(unsafe.Pointer(&sl))1181}11821183// utf16ToBuf function reinterprets []uint16 as []byte1184func utf16ToBuf(buf []uint16) []byte {1185sl := struct {1186addr *byte1187len int1188cap int1189}{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2}1190return *(*[]byte)(unsafe.Pointer(&sl))1191}11921193func wcslen(str []uint16) int {1194for i := 0; i < len(str); i++ {1195if str[i] == 0 {1196return i1197}1198}1199return len(str)1200}12011202// DeviceRegistryProperty method retrieves a specified Plug and Play device property.1203func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) {1204return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property)1205}12061207//sys setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW12081209// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device.1210func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {1211return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers)))1212}12131214// SetDeviceRegistryProperty function sets a Plug and Play device property for a device.1215func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {1216return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)1217}12181219// SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device.1220func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {1221str16, err := UTF16FromString(str)1222if err != nil {1223return err1224}1225err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))1226runtime.KeepAlive(str16)1227return err1228}12291230//sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW12311232// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.1233func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) {1234params := &DevInstallParams{}1235params.size = uint32(unsafe.Sizeof(*params))12361237return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params)1238}12391240// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element.1241func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) {1242return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData)1243}12441245//sys setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW12461247// SetupDiGetDeviceInstanceId function retrieves the instance ID of the device.1248func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) {1249reqSize := uint32(1024)1250for {1251buf := make([]uint16, reqSize)1252err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize)1253if err == ERROR_INSUFFICIENT_BUFFER {1254continue1255}1256if err != nil {1257return "", err1258}1259return UTF16ToString(buf), nil1260}1261}12621263// DeviceInstanceID method retrieves the instance ID of the device.1264func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) {1265return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData)1266}12671268// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element.1269//sys SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW12701271// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element.1272func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error {1273return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize)1274}12751276//sys SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW12771278// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element.1279func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error {1280return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams)1281}12821283// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element.1284//sys SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW12851286// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element.1287func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error {1288return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize)1289}12901291//sys setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW12921293// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer.1294func SetupDiClassNameFromGuidEx(classGUID *GUID, machineName string) (className string, err error) {1295var classNameUTF16 [MAX_CLASS_NAME_LEN]uint1612961297var machineNameUTF16 *uint161298if machineName != "" {1299machineNameUTF16, err = UTF16PtrFromString(machineName)1300if err != nil {1301return1302}1303}13041305err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0)1306if err != nil {1307return1308}13091310className = UTF16ToString(classNameUTF16[:])1311return1312}13131314//sys setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW13151316// 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.1317func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]GUID, error) {1318classNameUTF16, err := UTF16PtrFromString(className)1319if err != nil {1320return nil, err1321}13221323var machineNameUTF16 *uint161324if machineName != "" {1325machineNameUTF16, err = UTF16PtrFromString(machineName)1326if err != nil {1327return nil, err1328}1329}13301331reqSize := uint32(4)1332for {1333buf := make([]GUID, reqSize)1334err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)1335if err == ERROR_INSUFFICIENT_BUFFER {1336continue1337}1338if err != nil {1339return nil, err1340}1341return buf[:reqSize], nil1342}1343}13441345//sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice13461347// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set.1348func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) {1349data := &DevInfoData{}1350data.size = uint32(unsafe.Sizeof(*data))13511352return data, setupDiGetSelectedDevice(deviceInfoSet, data)1353}13541355// SelectedDevice method retrieves the selected device information element in a device information set.1356func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) {1357return SetupDiGetSelectedDevice(deviceInfoSet)1358}13591360// 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.1361//sys SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice13621363// 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.1364func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error {1365return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData)1366}13671368//sys setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) = setupapi.SetupUninstallOEMInfW13691370// SetupUninstallOEMInf uninstalls the specified driver.1371func SetupUninstallOEMInf(infFileName string, flags SUOI) error {1372infFileName16, err := UTF16PtrFromString(infFileName)1373if err != nil {1374return err1375}1376return setupUninstallOEMInf(infFileName16, flags, 0)1377}13781379//sys cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) = CfgMgr32.CM_MapCrToWin32Err13801381//sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_List_SizeW1382//sys cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_ListW13831384func CM_Get_Device_Interface_List(deviceID string, interfaceClass *GUID, flags uint32) ([]string, error) {1385deviceID16, err := UTF16PtrFromString(deviceID)1386if err != nil {1387return nil, err1388}1389var buf []uint161390var buflen uint321391for {1392if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS {1393return nil, ret1394}1395buf = make([]uint16, buflen)1396if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS {1397break1398} else if ret != CR_BUFFER_SMALL {1399return nil, ret1400}1401}1402var interfaces []string1403for i := 0; i < len(buf); {1404j := i + wcslen(buf[i:])1405if i < j {1406interfaces = append(interfaces, UTF16ToString(buf[i:j]))1407}1408i = j + 11409}1410if interfaces == nil {1411return nil, ERROR_NO_SUCH_DEVICE_INTERFACE1412}1413return interfaces, nil1414}14151416//sys cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_DevNode_Status14171418func CM_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) error {1419ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags)1420if ret == CR_SUCCESS {1421return nil1422}1423return ret1424}142514261427