go-tg-screenshot-bot
1425 строк · 67.2 Кб
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
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 (
24ERROR_EXPECTED_SECTION_NAME Errno = 0x20000000 | 0xC0000000 | 0
25ERROR_BAD_SECTION_NAME_LINE Errno = 0x20000000 | 0xC0000000 | 1
26ERROR_SECTION_NAME_TOO_LONG Errno = 0x20000000 | 0xC0000000 | 2
27ERROR_GENERAL_SYNTAX Errno = 0x20000000 | 0xC0000000 | 3
28ERROR_WRONG_INF_STYLE Errno = 0x20000000 | 0xC0000000 | 0x100
29ERROR_SECTION_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x101
30ERROR_LINE_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x102
31ERROR_NO_BACKUP Errno = 0x20000000 | 0xC0000000 | 0x103
32ERROR_NO_ASSOCIATED_CLASS Errno = 0x20000000 | 0xC0000000 | 0x200
33ERROR_CLASS_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x201
34ERROR_DUPLICATE_FOUND Errno = 0x20000000 | 0xC0000000 | 0x202
35ERROR_NO_DRIVER_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x203
36ERROR_KEY_DOES_NOT_EXIST Errno = 0x20000000 | 0xC0000000 | 0x204
37ERROR_INVALID_DEVINST_NAME Errno = 0x20000000 | 0xC0000000 | 0x205
38ERROR_INVALID_CLASS Errno = 0x20000000 | 0xC0000000 | 0x206
39ERROR_DEVINST_ALREADY_EXISTS Errno = 0x20000000 | 0xC0000000 | 0x207
40ERROR_DEVINFO_NOT_REGISTERED Errno = 0x20000000 | 0xC0000000 | 0x208
41ERROR_INVALID_REG_PROPERTY Errno = 0x20000000 | 0xC0000000 | 0x209
42ERROR_NO_INF Errno = 0x20000000 | 0xC0000000 | 0x20A
43ERROR_NO_SUCH_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x20B
44ERROR_CANT_LOAD_CLASS_ICON Errno = 0x20000000 | 0xC0000000 | 0x20C
45ERROR_INVALID_CLASS_INSTALLER Errno = 0x20000000 | 0xC0000000 | 0x20D
46ERROR_DI_DO_DEFAULT Errno = 0x20000000 | 0xC0000000 | 0x20E
47ERROR_DI_NOFILECOPY Errno = 0x20000000 | 0xC0000000 | 0x20F
48ERROR_INVALID_HWPROFILE Errno = 0x20000000 | 0xC0000000 | 0x210
49ERROR_NO_DEVICE_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x211
50ERROR_DEVINFO_LIST_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x212
51ERROR_DEVINFO_DATA_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x213
52ERROR_DI_BAD_PATH Errno = 0x20000000 | 0xC0000000 | 0x214
53ERROR_NO_CLASSINSTALL_PARAMS Errno = 0x20000000 | 0xC0000000 | 0x215
54ERROR_FILEQUEUE_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x216
55ERROR_BAD_SERVICE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x217
56ERROR_NO_CLASS_DRIVER_LIST Errno = 0x20000000 | 0xC0000000 | 0x218
57ERROR_NO_ASSOCIATED_SERVICE Errno = 0x20000000 | 0xC0000000 | 0x219
58ERROR_NO_DEFAULT_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x21A
59ERROR_DEVICE_INTERFACE_ACTIVE Errno = 0x20000000 | 0xC0000000 | 0x21B
60ERROR_DEVICE_INTERFACE_REMOVED Errno = 0x20000000 | 0xC0000000 | 0x21C
61ERROR_BAD_INTERFACE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x21D
62ERROR_NO_SUCH_INTERFACE_CLASS Errno = 0x20000000 | 0xC0000000 | 0x21E
63ERROR_INVALID_REFERENCE_STRING Errno = 0x20000000 | 0xC0000000 | 0x21F
64ERROR_INVALID_MACHINENAME Errno = 0x20000000 | 0xC0000000 | 0x220
65ERROR_REMOTE_COMM_FAILURE Errno = 0x20000000 | 0xC0000000 | 0x221
66ERROR_MACHINE_UNAVAILABLE Errno = 0x20000000 | 0xC0000000 | 0x222
67ERROR_NO_CONFIGMGR_SERVICES Errno = 0x20000000 | 0xC0000000 | 0x223
68ERROR_INVALID_PROPPAGE_PROVIDER Errno = 0x20000000 | 0xC0000000 | 0x224
69ERROR_NO_SUCH_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x225
70ERROR_DI_POSTPROCESSING_REQUIRED Errno = 0x20000000 | 0xC0000000 | 0x226
71ERROR_INVALID_COINSTALLER Errno = 0x20000000 | 0xC0000000 | 0x227
72ERROR_NO_COMPAT_DRIVERS Errno = 0x20000000 | 0xC0000000 | 0x228
73ERROR_NO_DEVICE_ICON Errno = 0x20000000 | 0xC0000000 | 0x229
74ERROR_INVALID_INF_LOGCONFIG Errno = 0x20000000 | 0xC0000000 | 0x22A
75ERROR_DI_DONT_INSTALL Errno = 0x20000000 | 0xC0000000 | 0x22B
76ERROR_INVALID_FILTER_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22C
77ERROR_NON_WINDOWS_NT_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22D
78ERROR_NON_WINDOWS_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22E
79ERROR_NO_CATALOG_FOR_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x22F
80ERROR_DEVINSTALL_QUEUE_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x230
81ERROR_NOT_DISABLEABLE Errno = 0x20000000 | 0xC0000000 | 0x231
82ERROR_CANT_REMOVE_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x232
83ERROR_INVALID_TARGET Errno = 0x20000000 | 0xC0000000 | 0x233
84ERROR_DRIVER_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x234
85ERROR_IN_WOW64 Errno = 0x20000000 | 0xC0000000 | 0x235
86ERROR_SET_SYSTEM_RESTORE_POINT Errno = 0x20000000 | 0xC0000000 | 0x236
87ERROR_SCE_DISABLED Errno = 0x20000000 | 0xC0000000 | 0x238
88ERROR_UNKNOWN_EXCEPTION Errno = 0x20000000 | 0xC0000000 | 0x239
89ERROR_PNP_REGISTRY_ERROR Errno = 0x20000000 | 0xC0000000 | 0x23A
90ERROR_REMOTE_REQUEST_UNSUPPORTED Errno = 0x20000000 | 0xC0000000 | 0x23B
91ERROR_NOT_AN_INSTALLED_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x23C
92ERROR_INF_IN_USE_BY_DEVICES Errno = 0x20000000 | 0xC0000000 | 0x23D
93ERROR_DI_FUNCTION_OBSOLETE Errno = 0x20000000 | 0xC0000000 | 0x23E
94ERROR_NO_AUTHENTICODE_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x23F
95ERROR_AUTHENTICODE_DISALLOWED Errno = 0x20000000 | 0xC0000000 | 0x240
96ERROR_AUTHENTICODE_TRUSTED_PUBLISHER Errno = 0x20000000 | 0xC0000000 | 0x241
97ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED Errno = 0x20000000 | 0xC0000000 | 0x242
98ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED Errno = 0x20000000 | 0xC0000000 | 0x243
99ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x244
100ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE Errno = 0x20000000 | 0xC0000000 | 0x245
101ERROR_DEVICE_INSTALLER_NOT_READY Errno = 0x20000000 | 0xC0000000 | 0x246
102ERROR_DRIVER_STORE_ADD_FAILED Errno = 0x20000000 | 0xC0000000 | 0x247
103ERROR_DEVICE_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x248
104ERROR_DRIVER_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x249
105ERROR_WRONG_INF_TYPE Errno = 0x20000000 | 0xC0000000 | 0x24A
106ERROR_FILE_HASH_NOT_IN_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x24B
107ERROR_DRIVER_STORE_DELETE_FAILED Errno = 0x20000000 | 0xC0000000 | 0x24C
108ERROR_UNRECOVERABLE_STACK_OVERFLOW Errno = 0x20000000 | 0xC0000000 | 0x300
109EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW
110ERROR_NO_DEFAULT_INTERFACE_DEVICE Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE
111ERROR_INTERFACE_DEVICE_ACTIVE Errno = ERROR_DEVICE_INTERFACE_ACTIVE
112ERROR_INTERFACE_DEVICE_REMOVED Errno = ERROR_DEVICE_INTERFACE_REMOVED
113ERROR_NO_SUCH_INTERFACE_DEVICE Errno = ERROR_NO_SUCH_DEVICE_INTERFACE
114)
115
116const (
117MAX_DEVICE_ID_LEN = 200
118MAX_DEVNODE_ID_LEN = MAX_DEVICE_ID_LEN
119MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null
120MAX_CLASS_NAME_LEN = 32
121MAX_PROFILE_LEN = 80
122MAX_CONFIG_VALUE = 9999
123MAX_INSTANCE_VALUE = 9999
124CONFIGMG_VERSION = 0x0400
125)
126
127// Maximum string length constants
128const (
129LINE_LEN = 256 // Windows 9x-compatible maximum for displayable strings coming from a device INF.
130MAX_INF_STRING_LENGTH = 4096 // Actual maximum size of an INF string (including string substitutions).
131MAX_INF_SECTION_NAME_LENGTH = 255 // For Windows 9x compatibility, INF section names should be constrained to 32 characters.
132MAX_TITLE_LEN = 60
133MAX_INSTRUCTION_LEN = 256
134MAX_LABEL_LEN = 30
135MAX_SERVICE_NAME_LEN = 256
136MAX_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").
141SP_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 {
155size uint32
156ClassGUID GUID
157DevInst 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 {
163size uint32 // Use unsafeSizeOf method
164ClassGUID GUID
165RemoteMachineHandle Handle
166remoteMachineName [SP_MAX_MACHINENAME_LENGTH]uint16
167}
168
169func (*DevInfoListDetailData) unsafeSizeOf() uint32 {
170if unsafe.Sizeof(uintptr(0)) == 4 {
171// Windows declares this with pshpack1.h
172return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName))
173}
174return uint32(unsafe.Sizeof(DevInfoListDetailData{}))
175}
176
177func (data *DevInfoListDetailData) RemoteMachineName() string {
178return UTF16ToString(data.remoteMachineName[:])
179}
180
181func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error {
182str, err := UTF16FromString(remoteMachineName)
183if err != nil {
184return err
185}
186copy(data.remoteMachineName[:], str)
187return nil
188}
189
190// DI_FUNCTION is function type for device installer
191type DI_FUNCTION uint32
192
193const (
194DIF_SELECTDEVICE DI_FUNCTION = 0x00000001
195DIF_INSTALLDEVICE DI_FUNCTION = 0x00000002
196DIF_ASSIGNRESOURCES DI_FUNCTION = 0x00000003
197DIF_PROPERTIES DI_FUNCTION = 0x00000004
198DIF_REMOVE DI_FUNCTION = 0x00000005
199DIF_FIRSTTIMESETUP DI_FUNCTION = 0x00000006
200DIF_FOUNDDEVICE DI_FUNCTION = 0x00000007
201DIF_SELECTCLASSDRIVERS DI_FUNCTION = 0x00000008
202DIF_VALIDATECLASSDRIVERS DI_FUNCTION = 0x00000009
203DIF_INSTALLCLASSDRIVERS DI_FUNCTION = 0x0000000A
204DIF_CALCDISKSPACE DI_FUNCTION = 0x0000000B
205DIF_DESTROYPRIVATEDATA DI_FUNCTION = 0x0000000C
206DIF_VALIDATEDRIVER DI_FUNCTION = 0x0000000D
207DIF_DETECT DI_FUNCTION = 0x0000000F
208DIF_INSTALLWIZARD DI_FUNCTION = 0x00000010
209DIF_DESTROYWIZARDDATA DI_FUNCTION = 0x00000011
210DIF_PROPERTYCHANGE DI_FUNCTION = 0x00000012
211DIF_ENABLECLASS DI_FUNCTION = 0x00000013
212DIF_DETECTVERIFY DI_FUNCTION = 0x00000014
213DIF_INSTALLDEVICEFILES DI_FUNCTION = 0x00000015
214DIF_UNREMOVE DI_FUNCTION = 0x00000016
215DIF_SELECTBESTCOMPATDRV DI_FUNCTION = 0x00000017
216DIF_ALLOW_INSTALL DI_FUNCTION = 0x00000018
217DIF_REGISTERDEVICE DI_FUNCTION = 0x00000019
218DIF_NEWDEVICEWIZARD_PRESELECT DI_FUNCTION = 0x0000001A
219DIF_NEWDEVICEWIZARD_SELECT DI_FUNCTION = 0x0000001B
220DIF_NEWDEVICEWIZARD_PREANALYZE DI_FUNCTION = 0x0000001C
221DIF_NEWDEVICEWIZARD_POSTANALYZE DI_FUNCTION = 0x0000001D
222DIF_NEWDEVICEWIZARD_FINISHINSTALL DI_FUNCTION = 0x0000001E
223DIF_INSTALLINTERFACES DI_FUNCTION = 0x00000020
224DIF_DETECTCANCEL DI_FUNCTION = 0x00000021
225DIF_REGISTER_COINSTALLERS DI_FUNCTION = 0x00000022
226DIF_ADDPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000023
227DIF_ADDPROPERTYPAGE_BASIC DI_FUNCTION = 0x00000024
228DIF_TROUBLESHOOTER DI_FUNCTION = 0x00000026
229DIF_POWERMESSAGEWAKE DI_FUNCTION = 0x00000027
230DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028
231DIF_UPDATEDRIVER_UI DI_FUNCTION = 0x00000029
232DIF_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 {
237size uint32
238Flags DI_FLAGS
239FlagsEx DI_FLAGSEX
240hwndParent uintptr
241InstallMsgHandler uintptr
242InstallMsgHandlerContext uintptr
243FileQueue HSPFILEQ
244_ uintptr
245_ uint32
246driverPath [MAX_PATH]uint16
247}
248
249func (params *DevInstallParams) DriverPath() string {
250return UTF16ToString(params.driverPath[:])
251}
252
253func (params *DevInstallParams) SetDriverPath(driverPath string) error {
254str, err := UTF16FromString(driverPath)
255if err != nil {
256return err
257}
258copy(params.driverPath[:], str)
259return nil
260}
261
262// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values
263type DI_FLAGS uint32
264
265const (
266// Flags for choosing a device
267DI_SHOWOEM DI_FLAGS = 0x00000001 // support Other... button
268DI_SHOWCOMPAT DI_FLAGS = 0x00000002 // show compatibility list
269DI_SHOWCLASS DI_FLAGS = 0x00000004 // show class list
270DI_SHOWALL DI_FLAGS = 0x00000007 // both class & compat list shown
271DI_NOVCP DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue
272DI_DIDCOMPAT DI_FLAGS = 0x00000010 // Searched for compatible devices
273DI_DIDCLASS DI_FLAGS = 0x00000020 // Searched for class devices
274DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible
275
276// Flags returned by DiInstallDevice to indicate need to reboot/restart
277DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect
278DI_NEEDREBOOT DI_FLAGS = 0x00000100 // ""
279
280// Flags for device installation
281DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk
282
283// Flags set by DiBuildDriverInfoList
284DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list
285
286// Flag indicates that device is disabled
287DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled
288
289// Flags for Device/Class Properties
290DI_GENERALPAGE_ADDED DI_FLAGS = 0x00001000
291DI_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.
294DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000
295
296// Flag to indicate that the sorting from the INF file should be used.
297DI_INF_IS_SORTED DI_FLAGS = 0x00008000
298
299// Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.
300DI_ENUMSINGLEINF DI_FLAGS = 0x00010000
301
302// Flag that prevents ConfigMgr from removing/re-enumerating devices during device
303// registration, installation, and deletion.
304DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000
305
306// The following flag can be used to install a device disabled
307DI_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.
311DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000
312
313// This flag is set if the Class Install params should be used.
314DI_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.
317DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000
318
319// Flags for device installation
320DI_QUIETINSTALL DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info
321DI_NOFILECOPY DI_FLAGS = 0x01000000 // No file Copy necessary
322DI_FORCECOPY DI_FLAGS = 0x02000000 // Force files to be copied from install path
323DI_DRIVERPAGE_ADDED DI_FLAGS = 0x04000000 // Prop provider added Driver page.
324DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg
325DI_OVERRIDE_INFFLAGS DI_FLAGS = 0x10000000 // Override INF flags
326DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props
327
328DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs
329
330DI_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 (
337DI_FLAGSEX_CI_FAILED DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer
338DI_FLAGSEX_FINISHINSTALL_ACTION DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context.
339DI_FLAGSEX_DIDINFOLIST DI_FLAGSEX = 0x00000010 // Did the Class Info List
340DI_FLAGSEX_DIDCOMPATINFO DI_FLAGSEX = 0x00000020 // Did the Compat Info List
341DI_FLAGSEX_FILTERCLASSES DI_FLAGSEX = 0x00000040
342DI_FLAGSEX_SETFAILEDINSTALL DI_FLAGSEX = 0x00000080
343DI_FLAGSEX_DEVICECHANGE DI_FLAGSEX = 0x00000100
344DI_FLAGSEX_ALWAYSWRITEIDS DI_FLAGSEX = 0x00000200
345DI_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.
346DI_FLAGSEX_ALLOWEXCLUDEDDRVS DI_FLAGSEX = 0x00000800
347DI_FLAGSEX_NOUIONQUERYREMOVE DI_FLAGSEX = 0x00001000
348DI_FLAGSEX_USECLASSFORCOMPAT DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.)
349DI_FLAGSEX_NO_DRVREG_MODIFY DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key.
350DI_FLAGSEX_IN_SYSTEM_SETUP DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup.
351DI_FLAGSEX_INET_DRIVER DI_FLAGSEX = 0x00020000 // Driver came from Windows Update
352DI_FLAGSEX_APPENDDRIVERLIST DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list.
353DI_FLAGSEX_PREINSTALLBACKUP DI_FLAGSEX = 0x00080000 // not used
354DI_FLAGSEX_BACKUPONREPLACE DI_FLAGSEX = 0x00100000 // not used
355DI_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)
356DI_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.
357DI_FLAGSEX_POWERPAGE_ADDED DI_FLAGSEX = 0x01000000 // class installer added their own power page
358DI_FLAGSEX_FILTERSIMILARDRIVERS DI_FLAGSEX = 0x02000000 // only include similar drivers in class list
359DI_FLAGSEX_INSTALLEDDRIVER DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list. Used in calls to SetupDiBuildDriverInfoList
360DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list
361DI_FLAGSEX_ALTPLATFORM_DRVSEARCH DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue
362DI_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.
363DI_FLAGSEX_RECURSIVESEARCH DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search
364DI_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 {
369size uint32
370InstallFunction DI_FUNCTION
371}
372
373func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader {
374hdr := &ClassInstallHeader{InstallFunction: installFunction}
375hdr.size = uint32(unsafe.Sizeof(*hdr))
376return hdr
377}
378
379// DICS_STATE specifies values indicating a change in a device's state
380type DICS_STATE uint32
381
382const (
383DICS_ENABLE DICS_STATE = 0x00000001 // The device is being enabled.
384DICS_DISABLE DICS_STATE = 0x00000002 // The device is being disabled.
385DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed.
386DICS_START DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile).
387DICS_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 (
394DICS_FLAG_GLOBAL DICS_FLAG = 0x00000001 // make change in all hardware profiles
395DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only
396DICS_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 {
401ClassInstallHeader ClassInstallHeader
402StateChange DICS_STATE
403Scope DICS_FLAG
404HwProfile uint32
405}
406
407// DI_REMOVEDEVICE specifies the scope of the device removal
408type DI_REMOVEDEVICE uint32
409
410const (
411DI_REMOVEDEVICE_GLOBAL DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry.
412DI_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 {
417ClassInstallHeader ClassInstallHeader
418Scope DI_REMOVEDEVICE
419HwProfile 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 {
424size uint32
425DriverType uint32
426_ uintptr
427description [LINE_LEN]uint16
428mfgName [LINE_LEN]uint16
429providerName [LINE_LEN]uint16
430DriverDate Filetime
431DriverVersion uint64
432}
433
434func (data *DrvInfoData) Description() string {
435return UTF16ToString(data.description[:])
436}
437
438func (data *DrvInfoData) SetDescription(description string) error {
439str, err := UTF16FromString(description)
440if err != nil {
441return err
442}
443copy(data.description[:], str)
444return nil
445}
446
447func (data *DrvInfoData) MfgName() string {
448return UTF16ToString(data.mfgName[:])
449}
450
451func (data *DrvInfoData) SetMfgName(mfgName string) error {
452str, err := UTF16FromString(mfgName)
453if err != nil {
454return err
455}
456copy(data.mfgName[:], str)
457return nil
458}
459
460func (data *DrvInfoData) ProviderName() string {
461return UTF16ToString(data.providerName[:])
462}
463
464func (data *DrvInfoData) SetProviderName(providerName string) error {
465str, err := UTF16FromString(providerName)
466if err != nil {
467return err
468}
469copy(data.providerName[:], str)
470return 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 {
475if data.DriverDate.HighDateTime > driverDate.HighDateTime {
476return true
477}
478if data.DriverDate.HighDateTime < driverDate.HighDateTime {
479return false
480}
481
482if data.DriverDate.LowDateTime > driverDate.LowDateTime {
483return true
484}
485if data.DriverDate.LowDateTime < driverDate.LowDateTime {
486return false
487}
488
489if data.DriverVersion > driverVersion {
490return true
491}
492if data.DriverVersion < driverVersion {
493return false
494}
495
496return false
497}
498
499// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure)
500type DrvInfoDetailData struct {
501size uint32 // Use unsafeSizeOf method
502InfDate Filetime
503compatIDsOffset uint32
504compatIDsLength uint32
505_ uintptr
506sectionName [LINE_LEN]uint16
507infFileName [MAX_PATH]uint16
508drvDescription [LINE_LEN]uint16
509hardwareID [1]uint16
510}
511
512func (*DrvInfoDetailData) unsafeSizeOf() uint32 {
513if unsafe.Sizeof(uintptr(0)) == 4 {
514// Windows declares this with pshpack1.h
515return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID))
516}
517return uint32(unsafe.Sizeof(DrvInfoDetailData{}))
518}
519
520func (data *DrvInfoDetailData) SectionName() string {
521return UTF16ToString(data.sectionName[:])
522}
523
524func (data *DrvInfoDetailData) InfFileName() string {
525return UTF16ToString(data.infFileName[:])
526}
527
528func (data *DrvInfoDetailData) DrvDescription() string {
529return UTF16ToString(data.drvDescription[:])
530}
531
532func (data *DrvInfoDetailData) HardwareID() string {
533if data.compatIDsOffset > 1 {
534bufW := data.getBuf()
535return UTF16ToString(bufW[:wcslen(bufW)])
536}
537
538return ""
539}
540
541func (data *DrvInfoDetailData) CompatIDs() []string {
542a := make([]string, 0)
543
544if data.compatIDsLength > 0 {
545bufW := data.getBuf()
546bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength]
547for i := 0; i < len(bufW); {
548j := i + wcslen(bufW[i:])
549if i < j {
550a = append(a, UTF16ToString(bufW[i:j]))
551}
552i = j + 1
553}
554}
555
556return a
557}
558
559func (data *DrvInfoDetailData) getBuf() []uint16 {
560len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2
561sl := struct {
562addr *uint16
563len int
564cap int
565}{&data.hardwareID[0], int(len), int(len)}
566return *(*[]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 {
571hwidLC := strings.ToLower(hwid)
572if strings.ToLower(data.HardwareID()) == hwidLC {
573return true
574}
575a := data.CompatIDs()
576for i := range a {
577if strings.ToLower(a[i]) == hwidLC {
578return true
579}
580}
581
582return false
583}
584
585// DICD flags control SetupDiCreateDeviceInfo
586type DICD uint32
587
588const (
589DICD_GENERATE_ID DICD = 0x00000001
590DICD_INHERIT_CLASSDRVS DICD = 0x00000002
591)
592
593// SUOI flags control SetupUninstallOEMInf
594type SUOI uint32
595
596const (
597SUOI_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 (
606SPDIT_NODRIVER SPDIT = 0x00000000
607SPDIT_CLASSDRIVER SPDIT = 0x00000001
608SPDIT_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 (
615DIGCF_DEFAULT DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE
616DIGCF_PRESENT DIGCF = 0x00000002
617DIGCF_ALLCLASSES DIGCF = 0x00000004
618DIGCF_PROFILE DIGCF = 0x00000008
619DIGCF_DEVICEINTERFACE DIGCF = 0x00000010
620)
621
622// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey.
623type DIREG uint32
624
625const (
626DIREG_DEV DIREG = 0x00000001 // Open/Create/Delete device key
627DIREG_DRV DIREG = 0x00000002 // Open/Create/Delete driver key
628DIREG_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 (
642SPDRP_DEVICEDESC SPDRP = 0x00000000 // DeviceDesc (R/W)
643SPDRP_HARDWAREID SPDRP = 0x00000001 // HardwareID (R/W)
644SPDRP_COMPATIBLEIDS SPDRP = 0x00000002 // CompatibleIDs (R/W)
645SPDRP_SERVICE SPDRP = 0x00000004 // Service (R/W)
646SPDRP_CLASS SPDRP = 0x00000007 // Class (R--tied to ClassGUID)
647SPDRP_CLASSGUID SPDRP = 0x00000008 // ClassGUID (R/W)
648SPDRP_DRIVER SPDRP = 0x00000009 // Driver (R/W)
649SPDRP_CONFIGFLAGS SPDRP = 0x0000000A // ConfigFlags (R/W)
650SPDRP_MFG SPDRP = 0x0000000B // Mfg (R/W)
651SPDRP_FRIENDLYNAME SPDRP = 0x0000000C // FriendlyName (R/W)
652SPDRP_LOCATION_INFORMATION SPDRP = 0x0000000D // LocationInformation (R/W)
653SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R)
654SPDRP_CAPABILITIES SPDRP = 0x0000000F // Capabilities (R)
655SPDRP_UI_NUMBER SPDRP = 0x00000010 // UiNumber (R)
656SPDRP_UPPERFILTERS SPDRP = 0x00000011 // UpperFilters (R/W)
657SPDRP_LOWERFILTERS SPDRP = 0x00000012 // LowerFilters (R/W)
658SPDRP_BUSTYPEGUID SPDRP = 0x00000013 // BusTypeGUID (R)
659SPDRP_LEGACYBUSTYPE SPDRP = 0x00000014 // LegacyBusType (R)
660SPDRP_BUSNUMBER SPDRP = 0x00000015 // BusNumber (R)
661SPDRP_ENUMERATOR_NAME SPDRP = 0x00000016 // Enumerator Name (R)
662SPDRP_SECURITY SPDRP = 0x00000017 // Security (R/W, binary form)
663SPDRP_SECURITY_SDS SPDRP = 0x00000018 // Security (W, SDS form)
664SPDRP_DEVTYPE SPDRP = 0x00000019 // Device Type (R/W)
665SPDRP_EXCLUSIVE SPDRP = 0x0000001A // Device is exclusive-access (R/W)
666SPDRP_CHARACTERISTICS SPDRP = 0x0000001B // Device Characteristics (R/W)
667SPDRP_ADDRESS SPDRP = 0x0000001C // Device Address (R)
668SPDRP_UI_NUMBER_DESC_FORMAT SPDRP = 0x0000001D // UiNumberDescFormat (R/W)
669SPDRP_DEVICE_POWER_DATA SPDRP = 0x0000001E // Device Power Data (R)
670SPDRP_REMOVAL_POLICY SPDRP = 0x0000001F // Removal Policy (R)
671SPDRP_REMOVAL_POLICY_HW_DEFAULT SPDRP = 0x00000020 // Hardware Removal Policy (R)
672SPDRP_REMOVAL_POLICY_OVERRIDE SPDRP = 0x00000021 // Removal Policy Override (RW)
673SPDRP_INSTALL_STATE SPDRP = 0x00000022 // Device Install State (R)
674SPDRP_LOCATION_PATHS SPDRP = 0x00000023 // Device Location Paths (R)
675SPDRP_BASE_CONTAINERID SPDRP = 0x00000024 // Base ContainerID (R)
676
677SPDRP_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 (
685DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000
686DEVPROP_TYPEMOD_LIST DEVPROPTYPE = 0x00002000
687
688DEVPROP_TYPE_EMPTY DEVPROPTYPE = 0x00000000
689DEVPROP_TYPE_NULL DEVPROPTYPE = 0x00000001
690DEVPROP_TYPE_SBYTE DEVPROPTYPE = 0x00000002
691DEVPROP_TYPE_BYTE DEVPROPTYPE = 0x00000003
692DEVPROP_TYPE_INT16 DEVPROPTYPE = 0x00000004
693DEVPROP_TYPE_UINT16 DEVPROPTYPE = 0x00000005
694DEVPROP_TYPE_INT32 DEVPROPTYPE = 0x00000006
695DEVPROP_TYPE_UINT32 DEVPROPTYPE = 0x00000007
696DEVPROP_TYPE_INT64 DEVPROPTYPE = 0x00000008
697DEVPROP_TYPE_UINT64 DEVPROPTYPE = 0x00000009
698DEVPROP_TYPE_FLOAT DEVPROPTYPE = 0x0000000A
699DEVPROP_TYPE_DOUBLE DEVPROPTYPE = 0x0000000B
700DEVPROP_TYPE_DECIMAL DEVPROPTYPE = 0x0000000C
701DEVPROP_TYPE_GUID DEVPROPTYPE = 0x0000000D
702DEVPROP_TYPE_CURRENCY DEVPROPTYPE = 0x0000000E
703DEVPROP_TYPE_DATE DEVPROPTYPE = 0x0000000F
704DEVPROP_TYPE_FILETIME DEVPROPTYPE = 0x00000010
705DEVPROP_TYPE_BOOLEAN DEVPROPTYPE = 0x00000011
706DEVPROP_TYPE_STRING DEVPROPTYPE = 0x00000012
707DEVPROP_TYPE_STRING_LIST DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST
708DEVPROP_TYPE_SECURITY_DESCRIPTOR DEVPROPTYPE = 0x00000013
709DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014
710DEVPROP_TYPE_DEVPROPKEY DEVPROPTYPE = 0x00000015
711DEVPROP_TYPE_DEVPROPTYPE DEVPROPTYPE = 0x00000016
712DEVPROP_TYPE_BINARY DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY
713DEVPROP_TYPE_ERROR DEVPROPTYPE = 0x00000017
714DEVPROP_TYPE_NTSTATUS DEVPROPTYPE = 0x00000018
715DEVPROP_TYPE_STRING_INDIRECT DEVPROPTYPE = 0x00000019
716
717MAX_DEVPROP_TYPE DEVPROPTYPE = 0x00000019
718MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000
719
720DEVPROP_MASK_TYPE DEVPROPTYPE = 0x00000FFF
721DEVPROP_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 {
735FmtID DEVPROPGUID
736PID DEVPROPID
737}
738
739// CONFIGRET is a return value or error code from cfgmgr32 APIs
740type CONFIGRET uint32
741
742func (ret CONFIGRET) Error() string {
743if win32Error, ok := ret.Unwrap().(Errno); ok {
744return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret))
745}
746return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret))
747}
748
749func (ret CONFIGRET) Win32Error(defaultError Errno) Errno {
750return cm_MapCrToWin32Err(ret, defaultError)
751}
752
753func (ret CONFIGRET) Unwrap() error {
754const noMatch = Errno(^uintptr(0))
755win32Error := ret.Win32Error(noMatch)
756if win32Error == noMatch {
757return nil
758}
759return win32Error
760}
761
762const (
763CR_SUCCESS CONFIGRET = 0x00000000
764CR_DEFAULT CONFIGRET = 0x00000001
765CR_OUT_OF_MEMORY CONFIGRET = 0x00000002
766CR_INVALID_POINTER CONFIGRET = 0x00000003
767CR_INVALID_FLAG CONFIGRET = 0x00000004
768CR_INVALID_DEVNODE CONFIGRET = 0x00000005
769CR_INVALID_DEVINST = CR_INVALID_DEVNODE
770CR_INVALID_RES_DES CONFIGRET = 0x00000006
771CR_INVALID_LOG_CONF CONFIGRET = 0x00000007
772CR_INVALID_ARBITRATOR CONFIGRET = 0x00000008
773CR_INVALID_NODELIST CONFIGRET = 0x00000009
774CR_DEVNODE_HAS_REQS CONFIGRET = 0x0000000A
775CR_DEVINST_HAS_REQS = CR_DEVNODE_HAS_REQS
776CR_INVALID_RESOURCEID CONFIGRET = 0x0000000B
777CR_DLVXD_NOT_FOUND CONFIGRET = 0x0000000C
778CR_NO_SUCH_DEVNODE CONFIGRET = 0x0000000D
779CR_NO_SUCH_DEVINST = CR_NO_SUCH_DEVNODE
780CR_NO_MORE_LOG_CONF CONFIGRET = 0x0000000E
781CR_NO_MORE_RES_DES CONFIGRET = 0x0000000F
782CR_ALREADY_SUCH_DEVNODE CONFIGRET = 0x00000010
783CR_ALREADY_SUCH_DEVINST = CR_ALREADY_SUCH_DEVNODE
784CR_INVALID_RANGE_LIST CONFIGRET = 0x00000011
785CR_INVALID_RANGE CONFIGRET = 0x00000012
786CR_FAILURE CONFIGRET = 0x00000013
787CR_NO_SUCH_LOGICAL_DEV CONFIGRET = 0x00000014
788CR_CREATE_BLOCKED CONFIGRET = 0x00000015
789CR_NOT_SYSTEM_VM CONFIGRET = 0x00000016
790CR_REMOVE_VETOED CONFIGRET = 0x00000017
791CR_APM_VETOED CONFIGRET = 0x00000018
792CR_INVALID_LOAD_TYPE CONFIGRET = 0x00000019
793CR_BUFFER_SMALL CONFIGRET = 0x0000001A
794CR_NO_ARBITRATOR CONFIGRET = 0x0000001B
795CR_NO_REGISTRY_HANDLE CONFIGRET = 0x0000001C
796CR_REGISTRY_ERROR CONFIGRET = 0x0000001D
797CR_INVALID_DEVICE_ID CONFIGRET = 0x0000001E
798CR_INVALID_DATA CONFIGRET = 0x0000001F
799CR_INVALID_API CONFIGRET = 0x00000020
800CR_DEVLOADER_NOT_READY CONFIGRET = 0x00000021
801CR_NEED_RESTART CONFIGRET = 0x00000022
802CR_NO_MORE_HW_PROFILES CONFIGRET = 0x00000023
803CR_DEVICE_NOT_THERE CONFIGRET = 0x00000024
804CR_NO_SUCH_VALUE CONFIGRET = 0x00000025
805CR_WRONG_TYPE CONFIGRET = 0x00000026
806CR_INVALID_PRIORITY CONFIGRET = 0x00000027
807CR_NOT_DISABLEABLE CONFIGRET = 0x00000028
808CR_FREE_RESOURCES CONFIGRET = 0x00000029
809CR_QUERY_VETOED CONFIGRET = 0x0000002A
810CR_CANT_SHARE_IRQ CONFIGRET = 0x0000002B
811CR_NO_DEPENDENT CONFIGRET = 0x0000002C
812CR_SAME_RESOURCES CONFIGRET = 0x0000002D
813CR_NO_SUCH_REGISTRY_KEY CONFIGRET = 0x0000002E
814CR_INVALID_MACHINENAME CONFIGRET = 0x0000002F
815CR_REMOTE_COMM_FAILURE CONFIGRET = 0x00000030
816CR_MACHINE_UNAVAILABLE CONFIGRET = 0x00000031
817CR_NO_CM_SERVICES CONFIGRET = 0x00000032
818CR_ACCESS_DENIED CONFIGRET = 0x00000033
819CR_CALL_NOT_IMPLEMENTED CONFIGRET = 0x00000034
820CR_INVALID_PROPERTY CONFIGRET = 0x00000035
821CR_DEVICE_INTERFACE_ACTIVE CONFIGRET = 0x00000036
822CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037
823CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038
824CR_INVALID_CONFLICT_LIST CONFIGRET = 0x00000039
825CR_INVALID_INDEX CONFIGRET = 0x0000003A
826CR_INVALID_STRUCTURE_SIZE CONFIGRET = 0x0000003B
827NUM_CR_RESULTS CONFIGRET = 0x0000003C
828)
829
830const (
831CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0 // only currently 'live' device interfaces
832CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not
833)
834
835const (
836DN_ROOT_ENUMERATED = 0x00000001 // Was enumerated by ROOT
837DN_DRIVER_LOADED = 0x00000002 // Has Register_Device_Driver
838DN_ENUM_LOADED = 0x00000004 // Has Register_Enumerator
839DN_STARTED = 0x00000008 // Is currently configured
840DN_MANUAL = 0x00000010 // Manually installed
841DN_NEED_TO_ENUM = 0x00000020 // May need reenumeration
842DN_NOT_FIRST_TIME = 0x00000040 // Has received a config
843DN_HARDWARE_ENUM = 0x00000080 // Enum generates hardware ID
844DN_LIAR = 0x00000100 // Lied about can reconfig once
845DN_HAS_MARK = 0x00000200 // Not CM_Create_DevInst lately
846DN_HAS_PROBLEM = 0x00000400 // Need device installer
847DN_FILTERED = 0x00000800 // Is filtered
848DN_MOVED = 0x00001000 // Has been moved
849DN_DISABLEABLE = 0x00002000 // Can be disabled
850DN_REMOVABLE = 0x00004000 // Can be removed
851DN_PRIVATE_PROBLEM = 0x00008000 // Has a private problem
852DN_MF_PARENT = 0x00010000 // Multi function parent
853DN_MF_CHILD = 0x00020000 // Multi function child
854DN_WILL_BE_REMOVED = 0x00040000 // DevInst is being removed
855DN_NOT_FIRST_TIMEE = 0x00080000 // Has received a config enumerate
856DN_STOP_FREE_RES = 0x00100000 // When child is stopped, free resources
857DN_REBAL_CANDIDATE = 0x00200000 // Don't skip during rebalance
858DN_BAD_PARTIAL = 0x00400000 // This devnode's log_confs do not have same resources
859DN_NT_ENUMERATOR = 0x00800000 // This devnode's is an NT enumerator
860DN_NT_DRIVER = 0x01000000 // This devnode's is an NT driver
861DN_NEEDS_LOCKING = 0x02000000 // Devnode need lock resume processing
862DN_ARM_WAKEUP = 0x04000000 // Devnode can be the wakeup device
863DN_APM_ENUMERATOR = 0x08000000 // APM aware enumerator
864DN_APM_DRIVER = 0x10000000 // APM aware driver
865DN_SILENT_INSTALL = 0x20000000 // Silent install
866DN_NO_SHOW_IN_DM = 0x40000000 // No show in device manager
867DN_BOOT_LOG_PROB = 0x80000000 // Had a problem during preassignment of boot log conf
868DN_NEED_RESTART = DN_LIAR // System needs to be restarted for this Devnode to work properly
869DN_DRIVER_BLOCKED = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode
870DN_LEGACY_DRIVER = DN_MOVED // This device is using a legacy driver
871DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK // One or more children have invalid IDs
872DN_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.
873DN_QUERY_REMOVE_PENDING = DN_MF_PARENT // Device is part of a set of related devices collectively pending query-removal
874DN_QUERY_REMOVE_ACTIVE = DN_MF_CHILD // Device is actively engaged in a query-remove IRP
875DN_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) {
882var machineNameUTF16 *uint16
883if machineName != "" {
884machineNameUTF16, err = UTF16PtrFromString(machineName)
885if err != nil {
886return
887}
888}
889return 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) {
896data := &DevInfoListDetailData{}
897data.size = data.unsafeSizeOf()
898
899return 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) {
904return 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) {
911deviceNameUTF16, err := UTF16PtrFromString(deviceName)
912if err != nil {
913return
914}
915
916var deviceDescriptionUTF16 *uint16
917if deviceDescription != "" {
918deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription)
919if err != nil {
920return
921}
922}
923
924data := &DevInfoData{}
925data.size = uint32(unsafe.Sizeof(*data))
926
927return 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) {
932return 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) {
939data := &DevInfoData{}
940data.size = uint32(unsafe.Sizeof(*data))
941
942return 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) {
947return 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 {
955return 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 {
962return 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 {
969return 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) {
976data := &DrvInfoData{}
977data.size = uint32(unsafe.Sizeof(*data))
978
979return 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) {
984return 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) {
991data := &DrvInfoData{}
992data.size = uint32(unsafe.Sizeof(*data))
993
994return 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) {
999return 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 {
1006return 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) {
1013reqSize := uint32(2048)
1014for {
1015buf := make([]byte, reqSize)
1016data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
1017data.size = data.unsafeSizeOf()
1018err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)
1019if err == ERROR_INSUFFICIENT_BUFFER {
1020continue
1021}
1022if err != nil {
1023return nil, err
1024}
1025data.size = reqSize
1026return 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) {
1032return 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 {
1039return 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) {
1046var enumeratorUTF16 *uint16
1047if enumerator != "" {
1048enumeratorUTF16, err = UTF16PtrFromString(enumerator)
1049if err != nil {
1050return
1051}
1052}
1053var machineNameUTF16 *uint16
1054if machineName != "" {
1055machineNameUTF16, err = UTF16PtrFromString(machineName)
1056if err != nil {
1057return
1058}
1059}
1060return 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 {
1068return 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) {
1076return 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) {
1083reqSize := uint32(256)
1084for {
1085var dataType DEVPROPTYPE
1086buf := make([]byte, reqSize)
1087err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0)
1088if err == ERROR_INSUFFICIENT_BUFFER {
1089continue
1090}
1091if err != nil {
1092return
1093}
1094switch dataType {
1095case DEVPROP_TYPE_STRING:
1096ret := UTF16ToString(bufToUTF16(buf))
1097runtime.KeepAlive(buf)
1098return ret, nil
1099}
1100return 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) {
1108reqSize := uint32(256)
1109for {
1110var dataType uint32
1111buf := make([]byte, reqSize)
1112err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)
1113if err == ERROR_INSUFFICIENT_BUFFER {
1114continue
1115}
1116if err != nil {
1117return
1118}
1119return getRegistryValue(buf[:reqSize], dataType)
1120}
1121}
1122
1123func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
1124switch dataType {
1125case REG_SZ:
1126ret := UTF16ToString(bufToUTF16(buf))
1127runtime.KeepAlive(buf)
1128return ret, nil
1129case REG_EXPAND_SZ:
1130value := UTF16ToString(bufToUTF16(buf))
1131if value == "" {
1132return "", nil
1133}
1134p, err := syscall.UTF16PtrFromString(value)
1135if err != nil {
1136return "", err
1137}
1138ret := make([]uint16, 100)
1139for {
1140n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret)))
1141if err != nil {
1142return "", err
1143}
1144if n <= uint32(len(ret)) {
1145return UTF16ToString(ret[:n]), nil
1146}
1147ret = make([]uint16, n)
1148}
1149case REG_BINARY:
1150return buf, nil
1151case REG_DWORD_LITTLE_ENDIAN:
1152return binary.LittleEndian.Uint32(buf), nil
1153case REG_DWORD_BIG_ENDIAN:
1154return binary.BigEndian.Uint32(buf), nil
1155case REG_MULTI_SZ:
1156bufW := bufToUTF16(buf)
1157a := []string{}
1158for i := 0; i < len(bufW); {
1159j := i + wcslen(bufW[i:])
1160if i < j {
1161a = append(a, UTF16ToString(bufW[i:j]))
1162}
1163i = j + 1
1164}
1165runtime.KeepAlive(buf)
1166return a, nil
1167case REG_QWORD_LITTLE_ENDIAN:
1168return binary.LittleEndian.Uint64(buf), nil
1169default:
1170return 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 {
1176sl := struct {
1177addr *uint16
1178len int
1179cap int
1180}{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2}
1181return *(*[]uint16)(unsafe.Pointer(&sl))
1182}
1183
1184// utf16ToBuf function reinterprets []uint16 as []byte
1185func utf16ToBuf(buf []uint16) []byte {
1186sl := struct {
1187addr *byte
1188len int
1189cap int
1190}{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2}
1191return *(*[]byte)(unsafe.Pointer(&sl))
1192}
1193
1194func wcslen(str []uint16) int {
1195for i := 0; i < len(str); i++ {
1196if str[i] == 0 {
1197return i
1198}
1199}
1200return 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) {
1205return 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 {
1212return 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 {
1217return 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 {
1222str16, err := UTF16FromString(str)
1223if err != nil {
1224return err
1225}
1226err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
1227runtime.KeepAlive(str16)
1228return 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) {
1235params := &DevInstallParams{}
1236params.size = uint32(unsafe.Sizeof(*params))
1237
1238return 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) {
1243return 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) {
1250reqSize := uint32(1024)
1251for {
1252buf := make([]uint16, reqSize)
1253err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize)
1254if err == ERROR_INSUFFICIENT_BUFFER {
1255continue
1256}
1257if err != nil {
1258return "", err
1259}
1260return UTF16ToString(buf), nil
1261}
1262}
1263
1264// DeviceInstanceID method retrieves the instance ID of the device.
1265func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) {
1266return 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 {
1274return 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 {
1281return 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 {
1289return 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) {
1296var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16
1297
1298var machineNameUTF16 *uint16
1299if machineName != "" {
1300machineNameUTF16, err = UTF16PtrFromString(machineName)
1301if err != nil {
1302return
1303}
1304}
1305
1306err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0)
1307if err != nil {
1308return
1309}
1310
1311className = UTF16ToString(classNameUTF16[:])
1312return
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) {
1319classNameUTF16, err := UTF16PtrFromString(className)
1320if err != nil {
1321return nil, err
1322}
1323
1324var machineNameUTF16 *uint16
1325if machineName != "" {
1326machineNameUTF16, err = UTF16PtrFromString(machineName)
1327if err != nil {
1328return nil, err
1329}
1330}
1331
1332reqSize := uint32(4)
1333for {
1334buf := make([]GUID, reqSize)
1335err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)
1336if err == ERROR_INSUFFICIENT_BUFFER {
1337continue
1338}
1339if err != nil {
1340return nil, err
1341}
1342return 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) {
1350data := &DevInfoData{}
1351data.size = uint32(unsafe.Sizeof(*data))
1352
1353return 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) {
1358return 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 {
1366return 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 {
1373infFileName16, err := UTF16PtrFromString(infFileName)
1374if err != nil {
1375return err
1376}
1377return 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) {
1386deviceID16, err := UTF16PtrFromString(deviceID)
1387if err != nil {
1388return nil, err
1389}
1390var buf []uint16
1391var buflen uint32
1392for {
1393if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS {
1394return nil, ret
1395}
1396buf = make([]uint16, buflen)
1397if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS {
1398break
1399} else if ret != CR_BUFFER_SMALL {
1400return nil, ret
1401}
1402}
1403var interfaces []string
1404for i := 0; i < len(buf); {
1405j := i + wcslen(buf[i:])
1406if i < j {
1407interfaces = append(interfaces, UTF16ToString(buf[i:j]))
1408}
1409i = j + 1
1410}
1411if interfaces == nil {
1412return nil, ERROR_NO_SUCH_DEVICE_INTERFACE
1413}
1414return 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 {
1420ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags)
1421if ret == CR_SUCCESS {
1422return nil
1423}
1424return ret
1425}
1426