cubefs

Форк
0
/x
/
setupapi_windows.go 
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

5
package windows
6

7
import (
8
	"encoding/binary"
9
	"errors"
10
	"fmt"
11
	"runtime"
12
	"strings"
13
	"syscall"
14
	"unsafe"
15
)
16

17
// This file contains functions that wrap SetupAPI.dll and CfgMgr32.dll,
18
// core system functions for managing hardware devices, drivers, and the PnP tree.
19
// Information about these APIs can be found at:
20
//     https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi
21
//     https://docs.microsoft.com/en-us/windows/win32/devinst/cfgmgr32-
22

23
const (
24
	ERROR_EXPECTED_SECTION_NAME                  Errno = 0x20000000 | 0xC0000000 | 0
25
	ERROR_BAD_SECTION_NAME_LINE                  Errno = 0x20000000 | 0xC0000000 | 1
26
	ERROR_SECTION_NAME_TOO_LONG                  Errno = 0x20000000 | 0xC0000000 | 2
27
	ERROR_GENERAL_SYNTAX                         Errno = 0x20000000 | 0xC0000000 | 3
28
	ERROR_WRONG_INF_STYLE                        Errno = 0x20000000 | 0xC0000000 | 0x100
29
	ERROR_SECTION_NOT_FOUND                      Errno = 0x20000000 | 0xC0000000 | 0x101
30
	ERROR_LINE_NOT_FOUND                         Errno = 0x20000000 | 0xC0000000 | 0x102
31
	ERROR_NO_BACKUP                              Errno = 0x20000000 | 0xC0000000 | 0x103
32
	ERROR_NO_ASSOCIATED_CLASS                    Errno = 0x20000000 | 0xC0000000 | 0x200
33
	ERROR_CLASS_MISMATCH                         Errno = 0x20000000 | 0xC0000000 | 0x201
34
	ERROR_DUPLICATE_FOUND                        Errno = 0x20000000 | 0xC0000000 | 0x202
35
	ERROR_NO_DRIVER_SELECTED                     Errno = 0x20000000 | 0xC0000000 | 0x203
36
	ERROR_KEY_DOES_NOT_EXIST                     Errno = 0x20000000 | 0xC0000000 | 0x204
37
	ERROR_INVALID_DEVINST_NAME                   Errno = 0x20000000 | 0xC0000000 | 0x205
38
	ERROR_INVALID_CLASS                          Errno = 0x20000000 | 0xC0000000 | 0x206
39
	ERROR_DEVINST_ALREADY_EXISTS                 Errno = 0x20000000 | 0xC0000000 | 0x207
40
	ERROR_DEVINFO_NOT_REGISTERED                 Errno = 0x20000000 | 0xC0000000 | 0x208
41
	ERROR_INVALID_REG_PROPERTY                   Errno = 0x20000000 | 0xC0000000 | 0x209
42
	ERROR_NO_INF                                 Errno = 0x20000000 | 0xC0000000 | 0x20A
43
	ERROR_NO_SUCH_DEVINST                        Errno = 0x20000000 | 0xC0000000 | 0x20B
44
	ERROR_CANT_LOAD_CLASS_ICON                   Errno = 0x20000000 | 0xC0000000 | 0x20C
45
	ERROR_INVALID_CLASS_INSTALLER                Errno = 0x20000000 | 0xC0000000 | 0x20D
46
	ERROR_DI_DO_DEFAULT                          Errno = 0x20000000 | 0xC0000000 | 0x20E
47
	ERROR_DI_NOFILECOPY                          Errno = 0x20000000 | 0xC0000000 | 0x20F
48
	ERROR_INVALID_HWPROFILE                      Errno = 0x20000000 | 0xC0000000 | 0x210
49
	ERROR_NO_DEVICE_SELECTED                     Errno = 0x20000000 | 0xC0000000 | 0x211
50
	ERROR_DEVINFO_LIST_LOCKED                    Errno = 0x20000000 | 0xC0000000 | 0x212
51
	ERROR_DEVINFO_DATA_LOCKED                    Errno = 0x20000000 | 0xC0000000 | 0x213
52
	ERROR_DI_BAD_PATH                            Errno = 0x20000000 | 0xC0000000 | 0x214
53
	ERROR_NO_CLASSINSTALL_PARAMS                 Errno = 0x20000000 | 0xC0000000 | 0x215
54
	ERROR_FILEQUEUE_LOCKED                       Errno = 0x20000000 | 0xC0000000 | 0x216
55
	ERROR_BAD_SERVICE_INSTALLSECT                Errno = 0x20000000 | 0xC0000000 | 0x217
56
	ERROR_NO_CLASS_DRIVER_LIST                   Errno = 0x20000000 | 0xC0000000 | 0x218
57
	ERROR_NO_ASSOCIATED_SERVICE                  Errno = 0x20000000 | 0xC0000000 | 0x219
58
	ERROR_NO_DEFAULT_DEVICE_INTERFACE            Errno = 0x20000000 | 0xC0000000 | 0x21A
59
	ERROR_DEVICE_INTERFACE_ACTIVE                Errno = 0x20000000 | 0xC0000000 | 0x21B
60
	ERROR_DEVICE_INTERFACE_REMOVED               Errno = 0x20000000 | 0xC0000000 | 0x21C
61
	ERROR_BAD_INTERFACE_INSTALLSECT              Errno = 0x20000000 | 0xC0000000 | 0x21D
62
	ERROR_NO_SUCH_INTERFACE_CLASS                Errno = 0x20000000 | 0xC0000000 | 0x21E
63
	ERROR_INVALID_REFERENCE_STRING               Errno = 0x20000000 | 0xC0000000 | 0x21F
64
	ERROR_INVALID_MACHINENAME                    Errno = 0x20000000 | 0xC0000000 | 0x220
65
	ERROR_REMOTE_COMM_FAILURE                    Errno = 0x20000000 | 0xC0000000 | 0x221
66
	ERROR_MACHINE_UNAVAILABLE                    Errno = 0x20000000 | 0xC0000000 | 0x222
67
	ERROR_NO_CONFIGMGR_SERVICES                  Errno = 0x20000000 | 0xC0000000 | 0x223
68
	ERROR_INVALID_PROPPAGE_PROVIDER              Errno = 0x20000000 | 0xC0000000 | 0x224
69
	ERROR_NO_SUCH_DEVICE_INTERFACE               Errno = 0x20000000 | 0xC0000000 | 0x225
70
	ERROR_DI_POSTPROCESSING_REQUIRED             Errno = 0x20000000 | 0xC0000000 | 0x226
71
	ERROR_INVALID_COINSTALLER                    Errno = 0x20000000 | 0xC0000000 | 0x227
72
	ERROR_NO_COMPAT_DRIVERS                      Errno = 0x20000000 | 0xC0000000 | 0x228
73
	ERROR_NO_DEVICE_ICON                         Errno = 0x20000000 | 0xC0000000 | 0x229
74
	ERROR_INVALID_INF_LOGCONFIG                  Errno = 0x20000000 | 0xC0000000 | 0x22A
75
	ERROR_DI_DONT_INSTALL                        Errno = 0x20000000 | 0xC0000000 | 0x22B
76
	ERROR_INVALID_FILTER_DRIVER                  Errno = 0x20000000 | 0xC0000000 | 0x22C
77
	ERROR_NON_WINDOWS_NT_DRIVER                  Errno = 0x20000000 | 0xC0000000 | 0x22D
78
	ERROR_NON_WINDOWS_DRIVER                     Errno = 0x20000000 | 0xC0000000 | 0x22E
79
	ERROR_NO_CATALOG_FOR_OEM_INF                 Errno = 0x20000000 | 0xC0000000 | 0x22F
80
	ERROR_DEVINSTALL_QUEUE_NONNATIVE             Errno = 0x20000000 | 0xC0000000 | 0x230
81
	ERROR_NOT_DISABLEABLE                        Errno = 0x20000000 | 0xC0000000 | 0x231
82
	ERROR_CANT_REMOVE_DEVINST                    Errno = 0x20000000 | 0xC0000000 | 0x232
83
	ERROR_INVALID_TARGET                         Errno = 0x20000000 | 0xC0000000 | 0x233
84
	ERROR_DRIVER_NONNATIVE                       Errno = 0x20000000 | 0xC0000000 | 0x234
85
	ERROR_IN_WOW64                               Errno = 0x20000000 | 0xC0000000 | 0x235
86
	ERROR_SET_SYSTEM_RESTORE_POINT               Errno = 0x20000000 | 0xC0000000 | 0x236
87
	ERROR_SCE_DISABLED                           Errno = 0x20000000 | 0xC0000000 | 0x238
88
	ERROR_UNKNOWN_EXCEPTION                      Errno = 0x20000000 | 0xC0000000 | 0x239
89
	ERROR_PNP_REGISTRY_ERROR                     Errno = 0x20000000 | 0xC0000000 | 0x23A
90
	ERROR_REMOTE_REQUEST_UNSUPPORTED             Errno = 0x20000000 | 0xC0000000 | 0x23B
91
	ERROR_NOT_AN_INSTALLED_OEM_INF               Errno = 0x20000000 | 0xC0000000 | 0x23C
92
	ERROR_INF_IN_USE_BY_DEVICES                  Errno = 0x20000000 | 0xC0000000 | 0x23D
93
	ERROR_DI_FUNCTION_OBSOLETE                   Errno = 0x20000000 | 0xC0000000 | 0x23E
94
	ERROR_NO_AUTHENTICODE_CATALOG                Errno = 0x20000000 | 0xC0000000 | 0x23F
95
	ERROR_AUTHENTICODE_DISALLOWED                Errno = 0x20000000 | 0xC0000000 | 0x240
96
	ERROR_AUTHENTICODE_TRUSTED_PUBLISHER         Errno = 0x20000000 | 0xC0000000 | 0x241
97
	ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED     Errno = 0x20000000 | 0xC0000000 | 0x242
98
	ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED     Errno = 0x20000000 | 0xC0000000 | 0x243
99
	ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH         Errno = 0x20000000 | 0xC0000000 | 0x244
100
	ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE         Errno = 0x20000000 | 0xC0000000 | 0x245
101
	ERROR_DEVICE_INSTALLER_NOT_READY             Errno = 0x20000000 | 0xC0000000 | 0x246
102
	ERROR_DRIVER_STORE_ADD_FAILED                Errno = 0x20000000 | 0xC0000000 | 0x247
103
	ERROR_DEVICE_INSTALL_BLOCKED                 Errno = 0x20000000 | 0xC0000000 | 0x248
104
	ERROR_DRIVER_INSTALL_BLOCKED                 Errno = 0x20000000 | 0xC0000000 | 0x249
105
	ERROR_WRONG_INF_TYPE                         Errno = 0x20000000 | 0xC0000000 | 0x24A
106
	ERROR_FILE_HASH_NOT_IN_CATALOG               Errno = 0x20000000 | 0xC0000000 | 0x24B
107
	ERROR_DRIVER_STORE_DELETE_FAILED             Errno = 0x20000000 | 0xC0000000 | 0x24C
108
	ERROR_UNRECOVERABLE_STACK_OVERFLOW           Errno = 0x20000000 | 0xC0000000 | 0x300
109
	EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW
110
	ERROR_NO_DEFAULT_INTERFACE_DEVICE            Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE
111
	ERROR_INTERFACE_DEVICE_ACTIVE                Errno = ERROR_DEVICE_INTERFACE_ACTIVE
112
	ERROR_INTERFACE_DEVICE_REMOVED               Errno = ERROR_DEVICE_INTERFACE_REMOVED
113
	ERROR_NO_SUCH_INTERFACE_DEVICE               Errno = ERROR_NO_SUCH_DEVICE_INTERFACE
114
)
115

116
const (
117
	MAX_DEVICE_ID_LEN   = 200
118
	MAX_DEVNODE_ID_LEN  = MAX_DEVICE_ID_LEN
119
	MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null
120
	MAX_CLASS_NAME_LEN  = 32
121
	MAX_PROFILE_LEN     = 80
122
	MAX_CONFIG_VALUE    = 9999
123
	MAX_INSTANCE_VALUE  = 9999
124
	CONFIGMG_VERSION    = 0x0400
125
)
126

127
// Maximum string length constants
128
const (
129
	LINE_LEN                    = 256  // Windows 9x-compatible maximum for displayable strings coming from a device INF.
130
	MAX_INF_STRING_LENGTH       = 4096 // Actual maximum size of an INF string (including string substitutions).
131
	MAX_INF_SECTION_NAME_LENGTH = 255  // For Windows 9x compatibility, INF section names should be constrained to 32 characters.
132
	MAX_TITLE_LEN               = 60
133
	MAX_INSTRUCTION_LEN         = 256
134
	MAX_LABEL_LEN               = 30
135
	MAX_SERVICE_NAME_LEN        = 256
136
	MAX_SUBTITLE_LEN            = 256
137
)
138

139
const (
140
	// SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0").
141
	SP_MAX_MACHINENAME_LENGTH = MAX_PATH + 3
142
)
143

144
// HSPFILEQ is type for setup file queue
145
type HSPFILEQ uintptr
146

147
// DevInfo holds reference to device information set
148
type DevInfo Handle
149

150
// DEVINST is a handle usually recognized by cfgmgr32 APIs
151
type DEVINST uint32
152

153
// DevInfoData is a device information structure (references a device instance that is a member of a device information set)
154
type DevInfoData struct {
155
	size      uint32
156
	ClassGUID GUID
157
	DevInst   DEVINST
158
	_         uintptr
159
}
160

161
// DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass).
162
type DevInfoListDetailData struct {
163
	size                uint32 // Use unsafeSizeOf method
164
	ClassGUID           GUID
165
	RemoteMachineHandle Handle
166
	remoteMachineName   [SP_MAX_MACHINENAME_LENGTH]uint16
167
}
168

169
func (*DevInfoListDetailData) unsafeSizeOf() uint32 {
170
	if unsafe.Sizeof(uintptr(0)) == 4 {
171
		// Windows declares this with pshpack1.h
172
		return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName))
173
	}
174
	return uint32(unsafe.Sizeof(DevInfoListDetailData{}))
175
}
176

177
func (data *DevInfoListDetailData) RemoteMachineName() string {
178
	return UTF16ToString(data.remoteMachineName[:])
179
}
180

181
func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error {
182
	str, err := UTF16FromString(remoteMachineName)
183
	if err != nil {
184
		return err
185
	}
186
	copy(data.remoteMachineName[:], str)
187
	return nil
188
}
189

190
// DI_FUNCTION is function type for device installer
191
type DI_FUNCTION uint32
192

193
const (
194
	DIF_SELECTDEVICE                   DI_FUNCTION = 0x00000001
195
	DIF_INSTALLDEVICE                  DI_FUNCTION = 0x00000002
196
	DIF_ASSIGNRESOURCES                DI_FUNCTION = 0x00000003
197
	DIF_PROPERTIES                     DI_FUNCTION = 0x00000004
198
	DIF_REMOVE                         DI_FUNCTION = 0x00000005
199
	DIF_FIRSTTIMESETUP                 DI_FUNCTION = 0x00000006
200
	DIF_FOUNDDEVICE                    DI_FUNCTION = 0x00000007
201
	DIF_SELECTCLASSDRIVERS             DI_FUNCTION = 0x00000008
202
	DIF_VALIDATECLASSDRIVERS           DI_FUNCTION = 0x00000009
203
	DIF_INSTALLCLASSDRIVERS            DI_FUNCTION = 0x0000000A
204
	DIF_CALCDISKSPACE                  DI_FUNCTION = 0x0000000B
205
	DIF_DESTROYPRIVATEDATA             DI_FUNCTION = 0x0000000C
206
	DIF_VALIDATEDRIVER                 DI_FUNCTION = 0x0000000D
207
	DIF_DETECT                         DI_FUNCTION = 0x0000000F
208
	DIF_INSTALLWIZARD                  DI_FUNCTION = 0x00000010
209
	DIF_DESTROYWIZARDDATA              DI_FUNCTION = 0x00000011
210
	DIF_PROPERTYCHANGE                 DI_FUNCTION = 0x00000012
211
	DIF_ENABLECLASS                    DI_FUNCTION = 0x00000013
212
	DIF_DETECTVERIFY                   DI_FUNCTION = 0x00000014
213
	DIF_INSTALLDEVICEFILES             DI_FUNCTION = 0x00000015
214
	DIF_UNREMOVE                       DI_FUNCTION = 0x00000016
215
	DIF_SELECTBESTCOMPATDRV            DI_FUNCTION = 0x00000017
216
	DIF_ALLOW_INSTALL                  DI_FUNCTION = 0x00000018
217
	DIF_REGISTERDEVICE                 DI_FUNCTION = 0x00000019
218
	DIF_NEWDEVICEWIZARD_PRESELECT      DI_FUNCTION = 0x0000001A
219
	DIF_NEWDEVICEWIZARD_SELECT         DI_FUNCTION = 0x0000001B
220
	DIF_NEWDEVICEWIZARD_PREANALYZE     DI_FUNCTION = 0x0000001C
221
	DIF_NEWDEVICEWIZARD_POSTANALYZE    DI_FUNCTION = 0x0000001D
222
	DIF_NEWDEVICEWIZARD_FINISHINSTALL  DI_FUNCTION = 0x0000001E
223
	DIF_INSTALLINTERFACES              DI_FUNCTION = 0x00000020
224
	DIF_DETECTCANCEL                   DI_FUNCTION = 0x00000021
225
	DIF_REGISTER_COINSTALLERS          DI_FUNCTION = 0x00000022
226
	DIF_ADDPROPERTYPAGE_ADVANCED       DI_FUNCTION = 0x00000023
227
	DIF_ADDPROPERTYPAGE_BASIC          DI_FUNCTION = 0x00000024
228
	DIF_TROUBLESHOOTER                 DI_FUNCTION = 0x00000026
229
	DIF_POWERMESSAGEWAKE               DI_FUNCTION = 0x00000027
230
	DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028
231
	DIF_UPDATEDRIVER_UI                DI_FUNCTION = 0x00000029
232
	DIF_FINISHINSTALL_ACTION           DI_FUNCTION = 0x0000002A
233
)
234

235
// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set)
236
type DevInstallParams struct {
237
	size                     uint32
238
	Flags                    DI_FLAGS
239
	FlagsEx                  DI_FLAGSEX
240
	hwndParent               uintptr
241
	InstallMsgHandler        uintptr
242
	InstallMsgHandlerContext uintptr
243
	FileQueue                HSPFILEQ
244
	_                        uintptr
245
	_                        uint32
246
	driverPath               [MAX_PATH]uint16
247
}
248

249
func (params *DevInstallParams) DriverPath() string {
250
	return UTF16ToString(params.driverPath[:])
251
}
252

253
func (params *DevInstallParams) SetDriverPath(driverPath string) error {
254
	str, err := UTF16FromString(driverPath)
255
	if err != nil {
256
		return err
257
	}
258
	copy(params.driverPath[:], str)
259
	return nil
260
}
261

262
// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values
263
type DI_FLAGS uint32
264

265
const (
266
	// Flags for choosing a device
267
	DI_SHOWOEM       DI_FLAGS = 0x00000001 // support Other... button
268
	DI_SHOWCOMPAT    DI_FLAGS = 0x00000002 // show compatibility list
269
	DI_SHOWCLASS     DI_FLAGS = 0x00000004 // show class list
270
	DI_SHOWALL       DI_FLAGS = 0x00000007 // both class & compat list shown
271
	DI_NOVCP         DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue
272
	DI_DIDCOMPAT     DI_FLAGS = 0x00000010 // Searched for compatible devices
273
	DI_DIDCLASS      DI_FLAGS = 0x00000020 // Searched for class devices
274
	DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible
275

276
	// Flags returned by DiInstallDevice to indicate need to reboot/restart
277
	DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect
278
	DI_NEEDREBOOT  DI_FLAGS = 0x00000100 // ""
279

280
	// Flags for device installation
281
	DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk
282

283
	// Flags set by DiBuildDriverInfoList
284
	DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list
285

286
	// Flag indicates that device is disabled
287
	DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled
288

289
	// Flags for Device/Class Properties
290
	DI_GENERALPAGE_ADDED  DI_FLAGS = 0x00001000
291
	DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000
292

293
	// Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated.
294
	DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000
295

296
	// Flag to indicate that the sorting from the INF file should be used.
297
	DI_INF_IS_SORTED DI_FLAGS = 0x00008000
298

299
	// Flag to indicate that only the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.
300
	DI_ENUMSINGLEINF DI_FLAGS = 0x00010000
301

302
	// Flag that prevents ConfigMgr from removing/re-enumerating devices during device
303
	// registration, installation, and deletion.
304
	DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000
305

306
	// The following flag can be used to install a device disabled
307
	DI_INSTALLDISABLED DI_FLAGS = 0x00040000
308

309
	// Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver
310
	// list from its existing class driver list, instead of the normal INF search.
311
	DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000
312

313
	// This flag is set if the Class Install params should be used.
314
	DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000
315

316
	// This flag is set if the caller of DiCallClassInstaller does NOT want the internal default action performed if the Class installer returns ERROR_DI_DO_DEFAULT.
317
	DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000
318

319
	// Flags for device installation
320
	DI_QUIETINSTALL        DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info
321
	DI_NOFILECOPY          DI_FLAGS = 0x01000000 // No file Copy necessary
322
	DI_FORCECOPY           DI_FLAGS = 0x02000000 // Force files to be copied from install path
323
	DI_DRIVERPAGE_ADDED    DI_FLAGS = 0x04000000 // Prop provider added Driver page.
324
	DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg
325
	DI_OVERRIDE_INFFLAGS   DI_FLAGS = 0x10000000 // Override INF flags
326
	DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props
327

328
	DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs
329

330
	DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install
331
)
332

333
// DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values
334
type DI_FLAGSEX uint32
335

336
const (
337
	DI_FLAGSEX_CI_FAILED                DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer
338
	DI_FLAGSEX_FINISHINSTALL_ACTION     DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context.
339
	DI_FLAGSEX_DIDINFOLIST              DI_FLAGSEX = 0x00000010 // Did the Class Info List
340
	DI_FLAGSEX_DIDCOMPATINFO            DI_FLAGSEX = 0x00000020 // Did the Compat Info List
341
	DI_FLAGSEX_FILTERCLASSES            DI_FLAGSEX = 0x00000040
342
	DI_FLAGSEX_SETFAILEDINSTALL         DI_FLAGSEX = 0x00000080
343
	DI_FLAGSEX_DEVICECHANGE             DI_FLAGSEX = 0x00000100
344
	DI_FLAGSEX_ALWAYSWRITEIDS           DI_FLAGSEX = 0x00000200
345
	DI_FLAGSEX_PROPCHANGE_PENDING       DI_FLAGSEX = 0x00000400 // One or more device property sheets have had changes made to them, and need to have a DIF_PROPERTYCHANGE occur.
346
	DI_FLAGSEX_ALLOWEXCLUDEDDRVS        DI_FLAGSEX = 0x00000800
347
	DI_FLAGSEX_NOUIONQUERYREMOVE        DI_FLAGSEX = 0x00001000
348
	DI_FLAGSEX_USECLASSFORCOMPAT        DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.)
349
	DI_FLAGSEX_NO_DRVREG_MODIFY         DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key.
350
	DI_FLAGSEX_IN_SYSTEM_SETUP          DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup.
351
	DI_FLAGSEX_INET_DRIVER              DI_FLAGSEX = 0x00020000 // Driver came from Windows Update
352
	DI_FLAGSEX_APPENDDRIVERLIST         DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list.
353
	DI_FLAGSEX_PREINSTALLBACKUP         DI_FLAGSEX = 0x00080000 // not used
354
	DI_FLAGSEX_BACKUPONREPLACE          DI_FLAGSEX = 0x00100000 // not used
355
	DI_FLAGSEX_DRIVERLIST_FROM_URL      DI_FLAGSEX = 0x00200000 // build driver list from INF(s) retrieved from URL specified in SP_DEVINSTALL_PARAMS.DriverPath (empty string means Windows Update website)
356
	DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS DI_FLAGSEX = 0x00800000 // Don't include old Internet drivers when building a driver list. Ignored on Windows Vista and later.
357
	DI_FLAGSEX_POWERPAGE_ADDED          DI_FLAGSEX = 0x01000000 // class installer added their own power page
358
	DI_FLAGSEX_FILTERSIMILARDRIVERS     DI_FLAGSEX = 0x02000000 // only include similar drivers in class list
359
	DI_FLAGSEX_INSTALLEDDRIVER          DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list.  Used in calls to SetupDiBuildDriverInfoList
360
	DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE  DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list
361
	DI_FLAGSEX_ALTPLATFORM_DRVSEARCH    DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue
362
	DI_FLAGSEX_RESTART_DEVICE_ONLY      DI_FLAGSEX = 0x20000000 // only restart the device drivers are being installed on as opposed to restarting all devices using those drivers.
363
	DI_FLAGSEX_RECURSIVESEARCH          DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search
364
	DI_FLAGSEX_SEARCH_PUBLISHED_INFS    DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search
365
)
366

367
// ClassInstallHeader is the first member of any class install parameters structure. It contains the device installation request code that defines the format of the rest of the install parameters structure.
368
type ClassInstallHeader struct {
369
	size            uint32
370
	InstallFunction DI_FUNCTION
371
}
372

373
func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader {
374
	hdr := &ClassInstallHeader{InstallFunction: installFunction}
375
	hdr.size = uint32(unsafe.Sizeof(*hdr))
376
	return hdr
377
}
378

379
// DICS_STATE specifies values indicating a change in a device's state
380
type DICS_STATE uint32
381

382
const (
383
	DICS_ENABLE     DICS_STATE = 0x00000001 // The device is being enabled.
384
	DICS_DISABLE    DICS_STATE = 0x00000002 // The device is being disabled.
385
	DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed.
386
	DICS_START      DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile).
387
	DICS_STOP       DICS_STATE = 0x00000005 // The device is being stopped. The driver stack will be unloaded and the CSCONFIGFLAG_DO_NOT_START flag will be set for the device.
388
)
389

390
// DICS_FLAG specifies the scope of a device property change
391
type DICS_FLAG uint32
392

393
const (
394
	DICS_FLAG_GLOBAL         DICS_FLAG = 0x00000001 // make change in all hardware profiles
395
	DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only
396
	DICS_FLAG_CONFIGGENERAL  DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete)
397
)
398

399
// PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function.
400
type PropChangeParams struct {
401
	ClassInstallHeader ClassInstallHeader
402
	StateChange        DICS_STATE
403
	Scope              DICS_FLAG
404
	HwProfile          uint32
405
}
406

407
// DI_REMOVEDEVICE specifies the scope of the device removal
408
type DI_REMOVEDEVICE uint32
409

410
const (
411
	DI_REMOVEDEVICE_GLOBAL         DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry.
412
	DI_REMOVEDEVICE_CONFIGSPECIFIC DI_REMOVEDEVICE = 0x00000002 // Make this change to only the hardware profile specified by HwProfile. this flag only applies to root-enumerated devices. When Windows removes the device from the last hardware profile in which it was configured, Windows performs a global removal.
413
)
414

415
// RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function.
416
type RemoveDeviceParams struct {
417
	ClassInstallHeader ClassInstallHeader
418
	Scope              DI_REMOVEDEVICE
419
	HwProfile          uint32
420
}
421

422
// DrvInfoData is driver information structure (member of a driver info list that may be associated with a particular device instance, or (globally) with a device information set)
423
type DrvInfoData struct {
424
	size          uint32
425
	DriverType    uint32
426
	_             uintptr
427
	description   [LINE_LEN]uint16
428
	mfgName       [LINE_LEN]uint16
429
	providerName  [LINE_LEN]uint16
430
	DriverDate    Filetime
431
	DriverVersion uint64
432
}
433

434
func (data *DrvInfoData) Description() string {
435
	return UTF16ToString(data.description[:])
436
}
437

438
func (data *DrvInfoData) SetDescription(description string) error {
439
	str, err := UTF16FromString(description)
440
	if err != nil {
441
		return err
442
	}
443
	copy(data.description[:], str)
444
	return nil
445
}
446

447
func (data *DrvInfoData) MfgName() string {
448
	return UTF16ToString(data.mfgName[:])
449
}
450

451
func (data *DrvInfoData) SetMfgName(mfgName string) error {
452
	str, err := UTF16FromString(mfgName)
453
	if err != nil {
454
		return err
455
	}
456
	copy(data.mfgName[:], str)
457
	return nil
458
}
459

460
func (data *DrvInfoData) ProviderName() string {
461
	return UTF16ToString(data.providerName[:])
462
}
463

464
func (data *DrvInfoData) SetProviderName(providerName string) error {
465
	str, err := UTF16FromString(providerName)
466
	if err != nil {
467
		return err
468
	}
469
	copy(data.providerName[:], str)
470
	return nil
471
}
472

473
// IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters.
474
func (data *DrvInfoData) IsNewer(driverDate Filetime, driverVersion uint64) bool {
475
	if data.DriverDate.HighDateTime > driverDate.HighDateTime {
476
		return true
477
	}
478
	if data.DriverDate.HighDateTime < driverDate.HighDateTime {
479
		return false
480
	}
481

482
	if data.DriverDate.LowDateTime > driverDate.LowDateTime {
483
		return true
484
	}
485
	if data.DriverDate.LowDateTime < driverDate.LowDateTime {
486
		return false
487
	}
488

489
	if data.DriverVersion > driverVersion {
490
		return true
491
	}
492
	if data.DriverVersion < driverVersion {
493
		return false
494
	}
495

496
	return false
497
}
498

499
// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure)
500
type DrvInfoDetailData struct {
501
	size            uint32 // Use unsafeSizeOf method
502
	InfDate         Filetime
503
	compatIDsOffset uint32
504
	compatIDsLength uint32
505
	_               uintptr
506
	sectionName     [LINE_LEN]uint16
507
	infFileName     [MAX_PATH]uint16
508
	drvDescription  [LINE_LEN]uint16
509
	hardwareID      [1]uint16
510
}
511

512
func (*DrvInfoDetailData) unsafeSizeOf() uint32 {
513
	if unsafe.Sizeof(uintptr(0)) == 4 {
514
		// Windows declares this with pshpack1.h
515
		return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID))
516
	}
517
	return uint32(unsafe.Sizeof(DrvInfoDetailData{}))
518
}
519

520
func (data *DrvInfoDetailData) SectionName() string {
521
	return UTF16ToString(data.sectionName[:])
522
}
523

524
func (data *DrvInfoDetailData) InfFileName() string {
525
	return UTF16ToString(data.infFileName[:])
526
}
527

528
func (data *DrvInfoDetailData) DrvDescription() string {
529
	return UTF16ToString(data.drvDescription[:])
530
}
531

532
func (data *DrvInfoDetailData) HardwareID() string {
533
	if data.compatIDsOffset > 1 {
534
		bufW := data.getBuf()
535
		return UTF16ToString(bufW[:wcslen(bufW)])
536
	}
537

538
	return ""
539
}
540

541
func (data *DrvInfoDetailData) CompatIDs() []string {
542
	a := make([]string, 0)
543

544
	if data.compatIDsLength > 0 {
545
		bufW := data.getBuf()
546
		bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength]
547
		for i := 0; i < len(bufW); {
548
			j := i + wcslen(bufW[i:])
549
			if i < j {
550
				a = append(a, UTF16ToString(bufW[i:j]))
551
			}
552
			i = j + 1
553
		}
554
	}
555

556
	return a
557
}
558

559
func (data *DrvInfoDetailData) getBuf() []uint16 {
560
	len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2
561
	sl := struct {
562
		addr *uint16
563
		len  int
564
		cap  int
565
	}{&data.hardwareID[0], int(len), int(len)}
566
	return *(*[]uint16)(unsafe.Pointer(&sl))
567
}
568

569
// IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list.
570
func (data *DrvInfoDetailData) IsCompatible(hwid string) bool {
571
	hwidLC := strings.ToLower(hwid)
572
	if strings.ToLower(data.HardwareID()) == hwidLC {
573
		return true
574
	}
575
	a := data.CompatIDs()
576
	for i := range a {
577
		if strings.ToLower(a[i]) == hwidLC {
578
			return true
579
		}
580
	}
581

582
	return false
583
}
584

585
// DICD flags control SetupDiCreateDeviceInfo
586
type DICD uint32
587

588
const (
589
	DICD_GENERATE_ID       DICD = 0x00000001
590
	DICD_INHERIT_CLASSDRVS DICD = 0x00000002
591
)
592

593
// SUOI flags control SetupUninstallOEMInf
594
type SUOI uint32
595

596
const (
597
	SUOI_FORCEDELETE SUOI = 0x0001
598
)
599

600
// SPDIT flags to distinguish between class drivers and
601
// device drivers. (Passed in 'DriverType' parameter of
602
// driver information list APIs)
603
type SPDIT uint32
604

605
const (
606
	SPDIT_NODRIVER     SPDIT = 0x00000000
607
	SPDIT_CLASSDRIVER  SPDIT = 0x00000001
608
	SPDIT_COMPATDRIVER SPDIT = 0x00000002
609
)
610

611
// DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs
612
type DIGCF uint32
613

614
const (
615
	DIGCF_DEFAULT         DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE
616
	DIGCF_PRESENT         DIGCF = 0x00000002
617
	DIGCF_ALLCLASSES      DIGCF = 0x00000004
618
	DIGCF_PROFILE         DIGCF = 0x00000008
619
	DIGCF_DEVICEINTERFACE DIGCF = 0x00000010
620
)
621

622
// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey.
623
type DIREG uint32
624

625
const (
626
	DIREG_DEV  DIREG = 0x00000001 // Open/Create/Delete device key
627
	DIREG_DRV  DIREG = 0x00000002 // Open/Create/Delete driver key
628
	DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key
629
)
630

631
// SPDRP specifies device registry property codes
632
// (Codes marked as read-only (R) may only be used for
633
// SetupDiGetDeviceRegistryProperty)
634
//
635
// These values should cover the same set of registry properties
636
// as defined by the CM_DRP codes in cfgmgr32.h.
637
//
638
// Note that SPDRP codes are zero based while CM_DRP codes are one based!
639
type SPDRP uint32
640

641
const (
642
	SPDRP_DEVICEDESC                  SPDRP = 0x00000000 // DeviceDesc (R/W)
643
	SPDRP_HARDWAREID                  SPDRP = 0x00000001 // HardwareID (R/W)
644
	SPDRP_COMPATIBLEIDS               SPDRP = 0x00000002 // CompatibleIDs (R/W)
645
	SPDRP_SERVICE                     SPDRP = 0x00000004 // Service (R/W)
646
	SPDRP_CLASS                       SPDRP = 0x00000007 // Class (R--tied to ClassGUID)
647
	SPDRP_CLASSGUID                   SPDRP = 0x00000008 // ClassGUID (R/W)
648
	SPDRP_DRIVER                      SPDRP = 0x00000009 // Driver (R/W)
649
	SPDRP_CONFIGFLAGS                 SPDRP = 0x0000000A // ConfigFlags (R/W)
650
	SPDRP_MFG                         SPDRP = 0x0000000B // Mfg (R/W)
651
	SPDRP_FRIENDLYNAME                SPDRP = 0x0000000C // FriendlyName (R/W)
652
	SPDRP_LOCATION_INFORMATION        SPDRP = 0x0000000D // LocationInformation (R/W)
653
	SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R)
654
	SPDRP_CAPABILITIES                SPDRP = 0x0000000F // Capabilities (R)
655
	SPDRP_UI_NUMBER                   SPDRP = 0x00000010 // UiNumber (R)
656
	SPDRP_UPPERFILTERS                SPDRP = 0x00000011 // UpperFilters (R/W)
657
	SPDRP_LOWERFILTERS                SPDRP = 0x00000012 // LowerFilters (R/W)
658
	SPDRP_BUSTYPEGUID                 SPDRP = 0x00000013 // BusTypeGUID (R)
659
	SPDRP_LEGACYBUSTYPE               SPDRP = 0x00000014 // LegacyBusType (R)
660
	SPDRP_BUSNUMBER                   SPDRP = 0x00000015 // BusNumber (R)
661
	SPDRP_ENUMERATOR_NAME             SPDRP = 0x00000016 // Enumerator Name (R)
662
	SPDRP_SECURITY                    SPDRP = 0x00000017 // Security (R/W, binary form)
663
	SPDRP_SECURITY_SDS                SPDRP = 0x00000018 // Security (W, SDS form)
664
	SPDRP_DEVTYPE                     SPDRP = 0x00000019 // Device Type (R/W)
665
	SPDRP_EXCLUSIVE                   SPDRP = 0x0000001A // Device is exclusive-access (R/W)
666
	SPDRP_CHARACTERISTICS             SPDRP = 0x0000001B // Device Characteristics (R/W)
667
	SPDRP_ADDRESS                     SPDRP = 0x0000001C // Device Address (R)
668
	SPDRP_UI_NUMBER_DESC_FORMAT       SPDRP = 0x0000001D // UiNumberDescFormat (R/W)
669
	SPDRP_DEVICE_POWER_DATA           SPDRP = 0x0000001E // Device Power Data (R)
670
	SPDRP_REMOVAL_POLICY              SPDRP = 0x0000001F // Removal Policy (R)
671
	SPDRP_REMOVAL_POLICY_HW_DEFAULT   SPDRP = 0x00000020 // Hardware Removal Policy (R)
672
	SPDRP_REMOVAL_POLICY_OVERRIDE     SPDRP = 0x00000021 // Removal Policy Override (RW)
673
	SPDRP_INSTALL_STATE               SPDRP = 0x00000022 // Device Install State (R)
674
	SPDRP_LOCATION_PATHS              SPDRP = 0x00000023 // Device Location Paths (R)
675
	SPDRP_BASE_CONTAINERID            SPDRP = 0x00000024 // Base ContainerID (R)
676

677
	SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals
678
)
679

680
// DEVPROPTYPE represents the property-data-type identifier that specifies the
681
// data type of a device property value in the unified device property model.
682
type DEVPROPTYPE uint32
683

684
const (
685
	DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000
686
	DEVPROP_TYPEMOD_LIST  DEVPROPTYPE = 0x00002000
687

688
	DEVPROP_TYPE_EMPTY                      DEVPROPTYPE = 0x00000000
689
	DEVPROP_TYPE_NULL                       DEVPROPTYPE = 0x00000001
690
	DEVPROP_TYPE_SBYTE                      DEVPROPTYPE = 0x00000002
691
	DEVPROP_TYPE_BYTE                       DEVPROPTYPE = 0x00000003
692
	DEVPROP_TYPE_INT16                      DEVPROPTYPE = 0x00000004
693
	DEVPROP_TYPE_UINT16                     DEVPROPTYPE = 0x00000005
694
	DEVPROP_TYPE_INT32                      DEVPROPTYPE = 0x00000006
695
	DEVPROP_TYPE_UINT32                     DEVPROPTYPE = 0x00000007
696
	DEVPROP_TYPE_INT64                      DEVPROPTYPE = 0x00000008
697
	DEVPROP_TYPE_UINT64                     DEVPROPTYPE = 0x00000009
698
	DEVPROP_TYPE_FLOAT                      DEVPROPTYPE = 0x0000000A
699
	DEVPROP_TYPE_DOUBLE                     DEVPROPTYPE = 0x0000000B
700
	DEVPROP_TYPE_DECIMAL                    DEVPROPTYPE = 0x0000000C
701
	DEVPROP_TYPE_GUID                       DEVPROPTYPE = 0x0000000D
702
	DEVPROP_TYPE_CURRENCY                   DEVPROPTYPE = 0x0000000E
703
	DEVPROP_TYPE_DATE                       DEVPROPTYPE = 0x0000000F
704
	DEVPROP_TYPE_FILETIME                   DEVPROPTYPE = 0x00000010
705
	DEVPROP_TYPE_BOOLEAN                    DEVPROPTYPE = 0x00000011
706
	DEVPROP_TYPE_STRING                     DEVPROPTYPE = 0x00000012
707
	DEVPROP_TYPE_STRING_LIST                DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST
708
	DEVPROP_TYPE_SECURITY_DESCRIPTOR        DEVPROPTYPE = 0x00000013
709
	DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014
710
	DEVPROP_TYPE_DEVPROPKEY                 DEVPROPTYPE = 0x00000015
711
	DEVPROP_TYPE_DEVPROPTYPE                DEVPROPTYPE = 0x00000016
712
	DEVPROP_TYPE_BINARY                     DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY
713
	DEVPROP_TYPE_ERROR                      DEVPROPTYPE = 0x00000017
714
	DEVPROP_TYPE_NTSTATUS                   DEVPROPTYPE = 0x00000018
715
	DEVPROP_TYPE_STRING_INDIRECT            DEVPROPTYPE = 0x00000019
716

717
	MAX_DEVPROP_TYPE    DEVPROPTYPE = 0x00000019
718
	MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000
719

720
	DEVPROP_MASK_TYPE    DEVPROPTYPE = 0x00000FFF
721
	DEVPROP_MASK_TYPEMOD DEVPROPTYPE = 0x0000F000
722
)
723

724
// DEVPROPGUID specifies a property category.
725
type DEVPROPGUID GUID
726

727
// DEVPROPID uniquely identifies the property within the property category.
728
type DEVPROPID uint32
729

730
const DEVPROPID_FIRST_USABLE DEVPROPID = 2
731

732
// DEVPROPKEY represents a device property key for a device property in the
733
// unified device property model.
734
type DEVPROPKEY struct {
735
	FmtID DEVPROPGUID
736
	PID   DEVPROPID
737
}
738

739
// CONFIGRET is a return value or error code from cfgmgr32 APIs
740
type CONFIGRET uint32
741

742
func (ret CONFIGRET) Error() string {
743
	if win32Error, ok := ret.Unwrap().(Errno); ok {
744
		return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret))
745
	}
746
	return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret))
747
}
748

749
func (ret CONFIGRET) Win32Error(defaultError Errno) Errno {
750
	return cm_MapCrToWin32Err(ret, defaultError)
751
}
752

753
func (ret CONFIGRET) Unwrap() error {
754
	const noMatch = Errno(^uintptr(0))
755
	win32Error := ret.Win32Error(noMatch)
756
	if win32Error == noMatch {
757
		return nil
758
	}
759
	return win32Error
760
}
761

762
const (
763
	CR_SUCCESS                  CONFIGRET = 0x00000000
764
	CR_DEFAULT                  CONFIGRET = 0x00000001
765
	CR_OUT_OF_MEMORY            CONFIGRET = 0x00000002
766
	CR_INVALID_POINTER          CONFIGRET = 0x00000003
767
	CR_INVALID_FLAG             CONFIGRET = 0x00000004
768
	CR_INVALID_DEVNODE          CONFIGRET = 0x00000005
769
	CR_INVALID_DEVINST                    = CR_INVALID_DEVNODE
770
	CR_INVALID_RES_DES          CONFIGRET = 0x00000006
771
	CR_INVALID_LOG_CONF         CONFIGRET = 0x00000007
772
	CR_INVALID_ARBITRATOR       CONFIGRET = 0x00000008
773
	CR_INVALID_NODELIST         CONFIGRET = 0x00000009
774
	CR_DEVNODE_HAS_REQS         CONFIGRET = 0x0000000A
775
	CR_DEVINST_HAS_REQS                   = CR_DEVNODE_HAS_REQS
776
	CR_INVALID_RESOURCEID       CONFIGRET = 0x0000000B
777
	CR_DLVXD_NOT_FOUND          CONFIGRET = 0x0000000C
778
	CR_NO_SUCH_DEVNODE          CONFIGRET = 0x0000000D
779
	CR_NO_SUCH_DEVINST                    = CR_NO_SUCH_DEVNODE
780
	CR_NO_MORE_LOG_CONF         CONFIGRET = 0x0000000E
781
	CR_NO_MORE_RES_DES          CONFIGRET = 0x0000000F
782
	CR_ALREADY_SUCH_DEVNODE     CONFIGRET = 0x00000010
783
	CR_ALREADY_SUCH_DEVINST               = CR_ALREADY_SUCH_DEVNODE
784
	CR_INVALID_RANGE_LIST       CONFIGRET = 0x00000011
785
	CR_INVALID_RANGE            CONFIGRET = 0x00000012
786
	CR_FAILURE                  CONFIGRET = 0x00000013
787
	CR_NO_SUCH_LOGICAL_DEV      CONFIGRET = 0x00000014
788
	CR_CREATE_BLOCKED           CONFIGRET = 0x00000015
789
	CR_NOT_SYSTEM_VM            CONFIGRET = 0x00000016
790
	CR_REMOVE_VETOED            CONFIGRET = 0x00000017
791
	CR_APM_VETOED               CONFIGRET = 0x00000018
792
	CR_INVALID_LOAD_TYPE        CONFIGRET = 0x00000019
793
	CR_BUFFER_SMALL             CONFIGRET = 0x0000001A
794
	CR_NO_ARBITRATOR            CONFIGRET = 0x0000001B
795
	CR_NO_REGISTRY_HANDLE       CONFIGRET = 0x0000001C
796
	CR_REGISTRY_ERROR           CONFIGRET = 0x0000001D
797
	CR_INVALID_DEVICE_ID        CONFIGRET = 0x0000001E
798
	CR_INVALID_DATA             CONFIGRET = 0x0000001F
799
	CR_INVALID_API              CONFIGRET = 0x00000020
800
	CR_DEVLOADER_NOT_READY      CONFIGRET = 0x00000021
801
	CR_NEED_RESTART             CONFIGRET = 0x00000022
802
	CR_NO_MORE_HW_PROFILES      CONFIGRET = 0x00000023
803
	CR_DEVICE_NOT_THERE         CONFIGRET = 0x00000024
804
	CR_NO_SUCH_VALUE            CONFIGRET = 0x00000025
805
	CR_WRONG_TYPE               CONFIGRET = 0x00000026
806
	CR_INVALID_PRIORITY         CONFIGRET = 0x00000027
807
	CR_NOT_DISABLEABLE          CONFIGRET = 0x00000028
808
	CR_FREE_RESOURCES           CONFIGRET = 0x00000029
809
	CR_QUERY_VETOED             CONFIGRET = 0x0000002A
810
	CR_CANT_SHARE_IRQ           CONFIGRET = 0x0000002B
811
	CR_NO_DEPENDENT             CONFIGRET = 0x0000002C
812
	CR_SAME_RESOURCES           CONFIGRET = 0x0000002D
813
	CR_NO_SUCH_REGISTRY_KEY     CONFIGRET = 0x0000002E
814
	CR_INVALID_MACHINENAME      CONFIGRET = 0x0000002F
815
	CR_REMOTE_COMM_FAILURE      CONFIGRET = 0x00000030
816
	CR_MACHINE_UNAVAILABLE      CONFIGRET = 0x00000031
817
	CR_NO_CM_SERVICES           CONFIGRET = 0x00000032
818
	CR_ACCESS_DENIED            CONFIGRET = 0x00000033
819
	CR_CALL_NOT_IMPLEMENTED     CONFIGRET = 0x00000034
820
	CR_INVALID_PROPERTY         CONFIGRET = 0x00000035
821
	CR_DEVICE_INTERFACE_ACTIVE  CONFIGRET = 0x00000036
822
	CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037
823
	CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038
824
	CR_INVALID_CONFLICT_LIST    CONFIGRET = 0x00000039
825
	CR_INVALID_INDEX            CONFIGRET = 0x0000003A
826
	CR_INVALID_STRUCTURE_SIZE   CONFIGRET = 0x0000003B
827
	NUM_CR_RESULTS              CONFIGRET = 0x0000003C
828
)
829

830
const (
831
	CM_GET_DEVICE_INTERFACE_LIST_PRESENT     = 0 // only currently 'live' device interfaces
832
	CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not
833
)
834

835
const (
836
	DN_ROOT_ENUMERATED       = 0x00000001        // Was enumerated by ROOT
837
	DN_DRIVER_LOADED         = 0x00000002        // Has Register_Device_Driver
838
	DN_ENUM_LOADED           = 0x00000004        // Has Register_Enumerator
839
	DN_STARTED               = 0x00000008        // Is currently configured
840
	DN_MANUAL                = 0x00000010        // Manually installed
841
	DN_NEED_TO_ENUM          = 0x00000020        // May need reenumeration
842
	DN_NOT_FIRST_TIME        = 0x00000040        // Has received a config
843
	DN_HARDWARE_ENUM         = 0x00000080        // Enum generates hardware ID
844
	DN_LIAR                  = 0x00000100        // Lied about can reconfig once
845
	DN_HAS_MARK              = 0x00000200        // Not CM_Create_DevInst lately
846
	DN_HAS_PROBLEM           = 0x00000400        // Need device installer
847
	DN_FILTERED              = 0x00000800        // Is filtered
848
	DN_MOVED                 = 0x00001000        // Has been moved
849
	DN_DISABLEABLE           = 0x00002000        // Can be disabled
850
	DN_REMOVABLE             = 0x00004000        // Can be removed
851
	DN_PRIVATE_PROBLEM       = 0x00008000        // Has a private problem
852
	DN_MF_PARENT             = 0x00010000        // Multi function parent
853
	DN_MF_CHILD              = 0x00020000        // Multi function child
854
	DN_WILL_BE_REMOVED       = 0x00040000        // DevInst is being removed
855
	DN_NOT_FIRST_TIMEE       = 0x00080000        // Has received a config enumerate
856
	DN_STOP_FREE_RES         = 0x00100000        // When child is stopped, free resources
857
	DN_REBAL_CANDIDATE       = 0x00200000        // Don't skip during rebalance
858
	DN_BAD_PARTIAL           = 0x00400000        // This devnode's log_confs do not have same resources
859
	DN_NT_ENUMERATOR         = 0x00800000        // This devnode's is an NT enumerator
860
	DN_NT_DRIVER             = 0x01000000        // This devnode's is an NT driver
861
	DN_NEEDS_LOCKING         = 0x02000000        // Devnode need lock resume processing
862
	DN_ARM_WAKEUP            = 0x04000000        // Devnode can be the wakeup device
863
	DN_APM_ENUMERATOR        = 0x08000000        // APM aware enumerator
864
	DN_APM_DRIVER            = 0x10000000        // APM aware driver
865
	DN_SILENT_INSTALL        = 0x20000000        // Silent install
866
	DN_NO_SHOW_IN_DM         = 0x40000000        // No show in device manager
867
	DN_BOOT_LOG_PROB         = 0x80000000        // Had a problem during preassignment of boot log conf
868
	DN_NEED_RESTART          = DN_LIAR           // System needs to be restarted for this Devnode to work properly
869
	DN_DRIVER_BLOCKED        = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode
870
	DN_LEGACY_DRIVER         = DN_MOVED          // This device is using a legacy driver
871
	DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK       // One or more children have invalid IDs
872
	DN_DEVICE_DISCONNECTED   = DN_NEEDS_LOCKING  // The function driver for a device reported that the device is not connected.  Typically this means a wireless device is out of range.
873
	DN_QUERY_REMOVE_PENDING  = DN_MF_PARENT      // Device is part of a set of related devices collectively pending query-removal
874
	DN_QUERY_REMOVE_ACTIVE   = DN_MF_CHILD       // Device is actively engaged in a query-remove IRP
875
	DN_CHANGEABLE_FLAGS      = DN_NOT_FIRST_TIME | DN_HARDWARE_ENUM | DN_HAS_MARK | DN_DISABLEABLE | DN_REMOVABLE | DN_MF_CHILD | DN_MF_PARENT | DN_NOT_FIRST_TIMEE | DN_STOP_FREE_RES | DN_REBAL_CANDIDATE | DN_NT_ENUMERATOR | DN_NT_DRIVER | DN_SILENT_INSTALL | DN_NO_SHOW_IN_DM
876
)
877

878
//sys	setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW
879

880
// SetupDiCreateDeviceInfoListEx function creates an empty device information set on a remote or a local computer and optionally associates the set with a device setup class.
881
func SetupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) {
882
	var machineNameUTF16 *uint16
883
	if machineName != "" {
884
		machineNameUTF16, err = UTF16PtrFromString(machineName)
885
		if err != nil {
886
			return
887
		}
888
	}
889
	return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0)
890
}
891

892
//sys	setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW
893

894
// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
895
func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) {
896
	data := &DevInfoListDetailData{}
897
	data.size = data.unsafeSizeOf()
898

899
	return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data)
900
}
901

902
// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
903
func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) {
904
	return SetupDiGetDeviceInfoListDetail(deviceInfoSet)
905
}
906

907
//sys	setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW
908

909
// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set.
910
func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) {
911
	deviceNameUTF16, err := UTF16PtrFromString(deviceName)
912
	if err != nil {
913
		return
914
	}
915

916
	var deviceDescriptionUTF16 *uint16
917
	if deviceDescription != "" {
918
		deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription)
919
		if err != nil {
920
			return
921
		}
922
	}
923

924
	data := &DevInfoData{}
925
	data.size = uint32(unsafe.Sizeof(*data))
926

927
	return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data)
928
}
929

930
// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set.
931
func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) {
932
	return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags)
933
}
934

935
//sys	setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo
936

937
// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set.
938
func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) {
939
	data := &DevInfoData{}
940
	data.size = uint32(unsafe.Sizeof(*data))
941

942
	return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data)
943
}
944

945
// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set.
946
func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) {
947
	return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex)
948
}
949

950
// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.
951
//sys	SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList
952

953
// Close method deletes a device information set and frees all associated memory.
954
func (deviceInfoSet DevInfo) Close() error {
955
	return SetupDiDestroyDeviceInfoList(deviceInfoSet)
956
}
957

958
//sys	SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList
959

960
// BuildDriverInfoList method builds a list of drivers that is associated with a specific device or with the global class driver list for a device information set.
961
func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
962
	return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
963
}
964

965
//sys	SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch
966

967
// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread.
968
func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error {
969
	return SetupDiCancelDriverInfoSearch(deviceInfoSet)
970
}
971

972
//sys	setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW
973

974
// SetupDiEnumDriverInfo function enumerates the members of a driver list.
975
func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
976
	data := &DrvInfoData{}
977
	data.size = uint32(unsafe.Sizeof(*data))
978

979
	return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data)
980
}
981

982
// EnumDriverInfo method enumerates the members of a driver list.
983
func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
984
	return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex)
985
}
986

987
//sys	setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW
988

989
// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element.
990
func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) {
991
	data := &DrvInfoData{}
992
	data.size = uint32(unsafe.Sizeof(*data))
993

994
	return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data)
995
}
996

997
// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element.
998
func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) {
999
	return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData)
1000
}
1001

1002
//sys	SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW
1003

1004
// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.
1005
func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error {
1006
	return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData)
1007
}
1008

1009
//sys	setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW
1010

1011
// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.
1012
func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
1013
	reqSize := uint32(2048)
1014
	for {
1015
		buf := make([]byte, reqSize)
1016
		data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
1017
		data.size = data.unsafeSizeOf()
1018
		err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)
1019
		if err == ERROR_INSUFFICIENT_BUFFER {
1020
			continue
1021
		}
1022
		if err != nil {
1023
			return nil, err
1024
		}
1025
		data.size = reqSize
1026
		return data, nil
1027
	}
1028
}
1029

1030
// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set.
1031
func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
1032
	return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData)
1033
}
1034

1035
//sys	SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList
1036

1037
// DestroyDriverInfoList method deletes a driver list.
1038
func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
1039
	return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
1040
}
1041

1042
//sys	setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiGetClassDevsExW
1043

1044
// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer.
1045
func SetupDiGetClassDevsEx(classGUID *GUID, enumerator string, hwndParent uintptr, flags DIGCF, deviceInfoSet DevInfo, machineName string) (handle DevInfo, err error) {
1046
	var enumeratorUTF16 *uint16
1047
	if enumerator != "" {
1048
		enumeratorUTF16, err = UTF16PtrFromString(enumerator)
1049
		if err != nil {
1050
			return
1051
		}
1052
	}
1053
	var machineNameUTF16 *uint16
1054
	if machineName != "" {
1055
		machineNameUTF16, err = UTF16PtrFromString(machineName)
1056
		if err != nil {
1057
			return
1058
		}
1059
	}
1060
	return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0)
1061
}
1062

1063
// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
1064
//sys	SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller
1065

1066
// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
1067
func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error {
1068
	return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData)
1069
}
1070

1071
// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.
1072
//sys	SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) [failretval==InvalidHandle] = setupapi.SetupDiOpenDevRegKey
1073

1074
// OpenDevRegKey method opens a registry key for device-specific configuration information.
1075
func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (Handle, error) {
1076
	return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired)
1077
}
1078

1079
//sys	setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) = setupapi.SetupDiGetDevicePropertyW
1080

1081
// SetupDiGetDeviceProperty function retrieves a specified device instance property.
1082
func SetupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY) (value interface{}, err error) {
1083
	reqSize := uint32(256)
1084
	for {
1085
		var dataType DEVPROPTYPE
1086
		buf := make([]byte, reqSize)
1087
		err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0)
1088
		if err == ERROR_INSUFFICIENT_BUFFER {
1089
			continue
1090
		}
1091
		if err != nil {
1092
			return
1093
		}
1094
		switch dataType {
1095
		case DEVPROP_TYPE_STRING:
1096
			ret := UTF16ToString(bufToUTF16(buf))
1097
			runtime.KeepAlive(buf)
1098
			return ret, nil
1099
		}
1100
		return nil, errors.New("unimplemented property type")
1101
	}
1102
}
1103

1104
//sys	setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW
1105

1106
// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property.
1107
func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) {
1108
	reqSize := uint32(256)
1109
	for {
1110
		var dataType uint32
1111
		buf := make([]byte, reqSize)
1112
		err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)
1113
		if err == ERROR_INSUFFICIENT_BUFFER {
1114
			continue
1115
		}
1116
		if err != nil {
1117
			return
1118
		}
1119
		return getRegistryValue(buf[:reqSize], dataType)
1120
	}
1121
}
1122

1123
func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
1124
	switch dataType {
1125
	case REG_SZ:
1126
		ret := UTF16ToString(bufToUTF16(buf))
1127
		runtime.KeepAlive(buf)
1128
		return ret, nil
1129
	case REG_EXPAND_SZ:
1130
		value := UTF16ToString(bufToUTF16(buf))
1131
		if value == "" {
1132
			return "", nil
1133
		}
1134
		p, err := syscall.UTF16PtrFromString(value)
1135
		if err != nil {
1136
			return "", err
1137
		}
1138
		ret := make([]uint16, 100)
1139
		for {
1140
			n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret)))
1141
			if err != nil {
1142
				return "", err
1143
			}
1144
			if n <= uint32(len(ret)) {
1145
				return UTF16ToString(ret[:n]), nil
1146
			}
1147
			ret = make([]uint16, n)
1148
		}
1149
	case REG_BINARY:
1150
		return buf, nil
1151
	case REG_DWORD_LITTLE_ENDIAN:
1152
		return binary.LittleEndian.Uint32(buf), nil
1153
	case REG_DWORD_BIG_ENDIAN:
1154
		return binary.BigEndian.Uint32(buf), nil
1155
	case REG_MULTI_SZ:
1156
		bufW := bufToUTF16(buf)
1157
		a := []string{}
1158
		for i := 0; i < len(bufW); {
1159
			j := i + wcslen(bufW[i:])
1160
			if i < j {
1161
				a = append(a, UTF16ToString(bufW[i:j]))
1162
			}
1163
			i = j + 1
1164
		}
1165
		runtime.KeepAlive(buf)
1166
		return a, nil
1167
	case REG_QWORD_LITTLE_ENDIAN:
1168
		return binary.LittleEndian.Uint64(buf), nil
1169
	default:
1170
		return nil, fmt.Errorf("Unsupported registry value type: %v", dataType)
1171
	}
1172
}
1173

1174
// bufToUTF16 function reinterprets []byte buffer as []uint16
1175
func bufToUTF16(buf []byte) []uint16 {
1176
	sl := struct {
1177
		addr *uint16
1178
		len  int
1179
		cap  int
1180
	}{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2}
1181
	return *(*[]uint16)(unsafe.Pointer(&sl))
1182
}
1183

1184
// utf16ToBuf function reinterprets []uint16 as []byte
1185
func utf16ToBuf(buf []uint16) []byte {
1186
	sl := struct {
1187
		addr *byte
1188
		len  int
1189
		cap  int
1190
	}{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2}
1191
	return *(*[]byte)(unsafe.Pointer(&sl))
1192
}
1193

1194
func wcslen(str []uint16) int {
1195
	for i := 0; i < len(str); i++ {
1196
		if str[i] == 0 {
1197
			return i
1198
		}
1199
	}
1200
	return len(str)
1201
}
1202

1203
// DeviceRegistryProperty method retrieves a specified Plug and Play device property.
1204
func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) {
1205
	return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property)
1206
}
1207

1208
//sys	setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW
1209

1210
// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device.
1211
func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
1212
	return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers)))
1213
}
1214

1215
// SetDeviceRegistryProperty function sets a Plug and Play device property for a device.
1216
func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
1217
	return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)
1218
}
1219

1220
// SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device.
1221
func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {
1222
	str16, err := UTF16FromString(str)
1223
	if err != nil {
1224
		return err
1225
	}
1226
	err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
1227
	runtime.KeepAlive(str16)
1228
	return err
1229
}
1230

1231
//sys	setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
1232

1233
// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
1234
func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) {
1235
	params := &DevInstallParams{}
1236
	params.size = uint32(unsafe.Sizeof(*params))
1237

1238
	return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params)
1239
}
1240

1241
// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element.
1242
func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) {
1243
	return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData)
1244
}
1245

1246
//sys	setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW
1247

1248
// SetupDiGetDeviceInstanceId function retrieves the instance ID of the device.
1249
func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) {
1250
	reqSize := uint32(1024)
1251
	for {
1252
		buf := make([]uint16, reqSize)
1253
		err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize)
1254
		if err == ERROR_INSUFFICIENT_BUFFER {
1255
			continue
1256
		}
1257
		if err != nil {
1258
			return "", err
1259
		}
1260
		return UTF16ToString(buf), nil
1261
	}
1262
}
1263

1264
// DeviceInstanceID method retrieves the instance ID of the device.
1265
func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) {
1266
	return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData)
1267
}
1268

1269
// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element.
1270
//sys	SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW
1271

1272
// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element.
1273
func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error {
1274
	return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize)
1275
}
1276

1277
//sys	SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW
1278

1279
// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element.
1280
func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error {
1281
	return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams)
1282
}
1283

1284
// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element.
1285
//sys	SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW
1286

1287
// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element.
1288
func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error {
1289
	return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize)
1290
}
1291

1292
//sys	setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW
1293

1294
// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer.
1295
func SetupDiClassNameFromGuidEx(classGUID *GUID, machineName string) (className string, err error) {
1296
	var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16
1297

1298
	var machineNameUTF16 *uint16
1299
	if machineName != "" {
1300
		machineNameUTF16, err = UTF16PtrFromString(machineName)
1301
		if err != nil {
1302
			return
1303
		}
1304
	}
1305

1306
	err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0)
1307
	if err != nil {
1308
		return
1309
	}
1310

1311
	className = UTF16ToString(classNameUTF16[:])
1312
	return
1313
}
1314

1315
//sys	setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW
1316

1317
// SetupDiClassGuidsFromNameEx function retrieves the GUIDs associated with the specified class name. This resulting list contains the classes currently installed on a local or remote computer.
1318
func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]GUID, error) {
1319
	classNameUTF16, err := UTF16PtrFromString(className)
1320
	if err != nil {
1321
		return nil, err
1322
	}
1323

1324
	var machineNameUTF16 *uint16
1325
	if machineName != "" {
1326
		machineNameUTF16, err = UTF16PtrFromString(machineName)
1327
		if err != nil {
1328
			return nil, err
1329
		}
1330
	}
1331

1332
	reqSize := uint32(4)
1333
	for {
1334
		buf := make([]GUID, reqSize)
1335
		err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)
1336
		if err == ERROR_INSUFFICIENT_BUFFER {
1337
			continue
1338
		}
1339
		if err != nil {
1340
			return nil, err
1341
		}
1342
		return buf[:reqSize], nil
1343
	}
1344
}
1345

1346
//sys	setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice
1347

1348
// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set.
1349
func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) {
1350
	data := &DevInfoData{}
1351
	data.size = uint32(unsafe.Sizeof(*data))
1352

1353
	return data, setupDiGetSelectedDevice(deviceInfoSet, data)
1354
}
1355

1356
// SelectedDevice method retrieves the selected device information element in a device information set.
1357
func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) {
1358
	return SetupDiGetSelectedDevice(deviceInfoSet)
1359
}
1360

1361
// SetupDiSetSelectedDevice function sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard.
1362
//sys	SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice
1363

1364
// SetSelectedDevice method sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard.
1365
func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error {
1366
	return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData)
1367
}
1368

1369
//sys	setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) = setupapi.SetupUninstallOEMInfW
1370

1371
// SetupUninstallOEMInf uninstalls the specified driver.
1372
func SetupUninstallOEMInf(infFileName string, flags SUOI) error {
1373
	infFileName16, err := UTF16PtrFromString(infFileName)
1374
	if err != nil {
1375
		return err
1376
	}
1377
	return setupUninstallOEMInf(infFileName16, flags, 0)
1378
}
1379

1380
//sys cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) = CfgMgr32.CM_MapCrToWin32Err
1381

1382
//sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_List_SizeW
1383
//sys cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_ListW
1384

1385
func CM_Get_Device_Interface_List(deviceID string, interfaceClass *GUID, flags uint32) ([]string, error) {
1386
	deviceID16, err := UTF16PtrFromString(deviceID)
1387
	if err != nil {
1388
		return nil, err
1389
	}
1390
	var buf []uint16
1391
	var buflen uint32
1392
	for {
1393
		if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS {
1394
			return nil, ret
1395
		}
1396
		buf = make([]uint16, buflen)
1397
		if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS {
1398
			break
1399
		} else if ret != CR_BUFFER_SMALL {
1400
			return nil, ret
1401
		}
1402
	}
1403
	var interfaces []string
1404
	for i := 0; i < len(buf); {
1405
		j := i + wcslen(buf[i:])
1406
		if i < j {
1407
			interfaces = append(interfaces, UTF16ToString(buf[i:j]))
1408
		}
1409
		i = j + 1
1410
	}
1411
	if interfaces == nil {
1412
		return nil, ERROR_NO_SUCH_DEVICE_INTERFACE
1413
	}
1414
	return interfaces, nil
1415
}
1416

1417
//sys cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_DevNode_Status
1418

1419
func CM_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) error {
1420
	ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags)
1421
	if ret == CR_SUCCESS {
1422
		return nil
1423
	}
1424
	return ret
1425
}
1426

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.