blob: 14027da3f3f117cc8b545ec62c131094b35ddf48 [file] [log] [blame]
kesavandc71914f2022-03-25 11:19:03 +05301// 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
5package windows
6
7import (
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
23const (
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
116const (
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
128const (
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
139const (
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
145type HSPFILEQ uintptr
146
147// DevInfo holds reference to device information set
148type DevInfo Handle
149
150// DEVINST is a handle usually recognized by cfgmgr32 APIs
151type DEVINST uint32
152
153// DevInfoData is a device information structure (references a device instance that is a member of a device information set)
154type 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).
162type DevInfoListDetailData struct {
163 size uint32 // Use unsafeSizeOf method
164 ClassGUID GUID
165 RemoteMachineHandle Handle
166 remoteMachineName [SP_MAX_MACHINENAME_LENGTH]uint16
167}
168
169func (*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
177func (data *DevInfoListDetailData) RemoteMachineName() string {
178 return UTF16ToString(data.remoteMachineName[:])
179}
180
181func (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
191type DI_FUNCTION uint32
192
193const (
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)
236type 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
249func (params *DevInstallParams) DriverPath() string {
250 return UTF16ToString(params.driverPath[:])
251}
252
253func (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
263type DI_FLAGS uint32
264
265const (
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
334type DI_FLAGSEX uint32
335
336const (
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.
368type ClassInstallHeader struct {
369 size uint32
370 InstallFunction DI_FUNCTION
371}
372
373func 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
380type DICS_STATE uint32
381
382const (
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
391type DICS_FLAG uint32
392
393const (
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.
400type 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
408type DI_REMOVEDEVICE uint32
409
410const (
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.
416type 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)
423type 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
434func (data *DrvInfoData) Description() string {
435 return UTF16ToString(data.description[:])
436}
437
438func (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
447func (data *DrvInfoData) MfgName() string {
448 return UTF16ToString(data.mfgName[:])
449}
450
451func (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
460func (data *DrvInfoData) ProviderName() string {
461 return UTF16ToString(data.providerName[:])
462}
463
464func (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.
474func (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)
500type 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
512func (*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
520func (data *DrvInfoDetailData) SectionName() string {
521 return UTF16ToString(data.sectionName[:])
522}
523
524func (data *DrvInfoDetailData) InfFileName() string {
525 return UTF16ToString(data.infFileName[:])
526}
527
528func (data *DrvInfoDetailData) DrvDescription() string {
529 return UTF16ToString(data.drvDescription[:])
530}
531
532func (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
541func (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
559func (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.
570func (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
586type DICD uint32
587
588const (
589 DICD_GENERATE_ID DICD = 0x00000001
590 DICD_INHERIT_CLASSDRVS DICD = 0x00000002
591)
592
593// SUOI flags control SetupUninstallOEMInf
594type SUOI uint32
595
596const (
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)
603type SPDIT uint32
604
605const (
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
612type DIGCF uint32
613
614const (
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.
623type DIREG uint32
624
625const (
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!
639type SPDRP uint32
640
641const (
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.
682type DEVPROPTYPE uint32
683
684const (
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.
725type DEVPROPGUID GUID
726
727// DEVPROPID uniquely identifies the property within the property category.
728type DEVPROPID uint32
729
730const DEVPROPID_FIRST_USABLE DEVPROPID = 2
731
732// DEVPROPKEY represents a device property key for a device property in the
733// unified device property model.
734type DEVPROPKEY struct {
735 FmtID DEVPROPGUID
736 PID DEVPROPID
737}
738
739// CONFIGRET is a return value or error code from cfgmgr32 APIs
740type CONFIGRET uint32
741
742func (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
749func (ret CONFIGRET) Win32Error(defaultError Errno) Errno {
750 return cm_MapCrToWin32Err(ret, defaultError)
751}
752
753func (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
762const (
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
830const (
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
835const (
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.
881func 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.
895func 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.
903func (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.
910func 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.
931func (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.
938func 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.
946func (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.
954func (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.
961func (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.
968func (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.
975func 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.
983func (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.
990func 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.
998func (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.
1005func (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.
1012func 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.
1031func (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.
1038func (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.
1045func 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).
1067func (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.
1075func (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.
1082func 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.
1107func 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
1123func 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
1175func 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
1185func 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
1194func 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.
1204func (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.
1211func 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.
1216func (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.
1221func (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.
1234func 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.
1242func (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.
1249func 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.
1265func (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.
1273func (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.
1280func (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.
1288func (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.
1295func 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.
1318func 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.
1349func 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.
1357func (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.
1365func (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.
1372func 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
1385func 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
1419func 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}