kesavand | c71914f | 2022-03-25 11:19:03 +0530 | [diff] [blame^] | 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 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 | } |