summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2019-02-01 13:59:53 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2019-02-05 12:59:42 +0100
commitf1d5db6547738a24b660d766d0690bb9642cc1bb (patch)
tree0f576f51544ad37c36f2f7a878cf6922b4afacf1
parentdce5192d860888e6af3e7fa8a7e4b2c776274e69 (diff)
Add support for setupapi.SetupDi(Get|Set)DeviceInstallParams()
Signed-off-by: Simon Rozman <simon@rozman.si>
-rw-r--r--setupapi/setupapi_windows.go45
-rw-r--r--setupapi/setupapi_windows_test.go24
-rw-r--r--setupapi/types_windows.go132
-rw-r--r--setupapi/zsetupapi_windows.go26
4 files changed, 227 insertions, 0 deletions
diff --git a/setupapi/setupapi_windows.go b/setupapi/setupapi_windows.go
index 282b9d0..3fa0cbb 100644
--- a/setupapi/setupapi_windows.go
+++ b/setupapi/setupapi_windows.go
@@ -18,6 +18,8 @@ import (
//sys setupDiGetDeviceInfoListDetail(DeviceInfoSet DevInfo, DeviceInfoSetDetailData *_SP_DEVINFO_LIST_DETAIL_DATA) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW
//sys setupDiEnumDeviceInfo(DeviceInfoSet DevInfo, MemberIndex uint32, DeviceInfoData *SP_DEVINFO_DATA) (err error) = setupapi.SetupDiEnumDeviceInfo
//sys setupDiOpenDevRegKey(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key windows.Handle, err error) [failretval==windows.InvalidHandle] = setupapi.SetupDiOpenDevRegKey
+//sys setupDiGetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, DeviceInstallParams *_SP_DEVINSTALL_PARAMS) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
+//sys setupDiSetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, DeviceInstallParams *_SP_DEVINSTALL_PARAMS) (err error) = setupapi.SetupDiSetDeviceInstallParamsW
// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer.
func SetupDiGetClassDevsEx(ClassGUID *windows.GUID, Enumerator string, hwndParent uintptr, Flags DIGCF, DeviceInfoSet DevInfo, MachineName string) (handle DevInfo, err error) {
@@ -67,3 +69,46 @@ func SetupDiOpenDevRegKey(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA
handle, err := setupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired)
return registry.Key(handle), err
}
+
+// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
+func SetupDiGetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA) (data *DevInstallParams, err error) {
+ var DeviceInstallParams _SP_DEVINSTALL_PARAMS
+ DeviceInstallParams.Size = uint32(unsafe.Sizeof(DeviceInstallParams))
+
+ err = setupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &DeviceInstallParams)
+ if err != nil {
+ return
+ }
+
+ data = &DevInstallParams{
+ Flags: DeviceInstallParams.Flags,
+ FlagsEx: DeviceInstallParams.FlagsEx,
+ hwndParent: DeviceInstallParams.hwndParent,
+ InstallMsgHandler: DeviceInstallParams.InstallMsgHandler,
+ InstallMsgHandlerContext: DeviceInstallParams.InstallMsgHandlerContext,
+ FileQueue: DeviceInstallParams.FileQueue,
+ DriverPath: windows.UTF16ToString(DeviceInstallParams.DriverPath[:]),
+ }
+ return
+}
+
+// SetupDiSetDeviceInstallParams function sets device installation parameters for a device information set or a particular device information element.
+func SetupDiSetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, DeviceInstallParams *DevInstallParams) (err error) {
+ data := _SP_DEVINSTALL_PARAMS{
+ Flags: DeviceInstallParams.Flags,
+ FlagsEx: DeviceInstallParams.FlagsEx,
+ hwndParent: DeviceInstallParams.hwndParent,
+ InstallMsgHandler: DeviceInstallParams.InstallMsgHandler,
+ InstallMsgHandlerContext: DeviceInstallParams.InstallMsgHandlerContext,
+ FileQueue: DeviceInstallParams.FileQueue,
+ }
+ data.Size = uint32(unsafe.Sizeof(data))
+
+ _p0, err := syscall.UTF16FromString(DeviceInstallParams.DriverPath)
+ if err != nil {
+ return
+ }
+ copy(data.DriverPath[:], _p0)
+
+ return setupDiSetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &data)
+}
diff --git a/setupapi/setupapi_windows_test.go b/setupapi/setupapi_windows_test.go
index 25e712f..1d3c33d 100644
--- a/setupapi/setupapi_windows_test.go
+++ b/setupapi/setupapi_windows_test.go
@@ -135,3 +135,27 @@ func TestSetupDiOpenDevRegKey(t *testing.T) {
defer key.Close()
}
}
+
+func TestSetupDiGetDeviceInstallParams(t *testing.T) {
+ devInfoList, err := SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, DIGCF_PRESENT, DevInfo(0), "")
+ if err != nil {
+ t.Errorf("Error calling SetupDiGetClassDevsEx: %s", err.Error())
+ }
+ defer devInfoList.Close()
+
+ var data SP_DEVINFO_DATA
+ for i := 0; true; i++ {
+ err := SetupDiEnumDeviceInfo(devInfoList, i, &data)
+ if err != nil {
+ if errWin, ok := err.(syscall.Errno); ok && errWin == 259 /*ERROR_NO_MORE_ITEMS*/ {
+ break
+ }
+ continue
+ }
+
+ _, err = SetupDiGetDeviceInstallParams(devInfoList, &data)
+ if err != nil {
+ t.Errorf("Error calling SetupDiOpenDevRegKey: %s", err.Error())
+ }
+ }
+}
diff --git a/setupapi/types_windows.go b/setupapi/types_windows.go
index ef0725a..e8fe650 100644
--- a/setupapi/types_windows.go
+++ b/setupapi/types_windows.go
@@ -76,3 +76,135 @@ const (
DIREG_DRV DIREG = 0x00000002 // Open/Create/Delete driver key
DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key
)
+
+// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values
+type DI_FLAGS uint32
+
+const (
+ // Flags for choosing a device
+ DI_SHOWOEM DI_FLAGS = 0x00000001 // support Other... button
+ DI_SHOWCOMPAT DI_FLAGS = 0x00000002 // show compatibility list
+ DI_SHOWCLASS DI_FLAGS = 0x00000004 // show class list
+ DI_SHOWALL DI_FLAGS = 0x00000007 // both class & compat list shown
+ DI_NOVCP DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue
+ DI_DIDCOMPAT DI_FLAGS = 0x00000010 // Searched for compatible devices
+ DI_DIDCLASS DI_FLAGS = 0x00000020 // Searched for class devices
+ DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible
+
+ // Flags returned by DiInstallDevice to indicate need to reboot/restart
+ DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect
+ DI_NEEDREBOOT DI_FLAGS = 0x00000100 // ""
+
+ // Flags for device installation
+ DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk
+
+ // Flags set by DiBuildDriverInfoList
+ DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list
+
+ // Flag indicates that device is disabled
+ DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled
+
+ // Flags for Device/Class Properties
+ DI_GENERALPAGE_ADDED DI_FLAGS = 0x00001000
+ DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000
+
+ // Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated.
+ DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000
+
+ // Flag to indicate that the sorting from the INF file should be used.
+ DI_INF_IS_SORTED DI_FLAGS = 0x00008000
+
+ // Flag to indicate that only the the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched.
+ DI_ENUMSINGLEINF DI_FLAGS = 0x00010000
+
+ // Flag that prevents ConfigMgr from removing/re-enumerating devices during device
+ // registration, installation, and deletion.
+ DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000
+
+ // The following flag can be used to install a device disabled
+ DI_INSTALLDISABLED DI_FLAGS = 0x00040000
+
+ // Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver
+ // list from its existing class driver list, instead of the normal INF search.
+ DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000
+
+ // This flag is set if the Class Install params should be used.
+ DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000
+
+ // 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.
+ DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000
+
+ // Flags for device installation
+ DI_QUIETINSTALL DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info
+ DI_NOFILECOPY DI_FLAGS = 0x01000000 // No file Copy necessary
+ DI_FORCECOPY DI_FLAGS = 0x02000000 // Force files to be copied from install path
+ DI_DRIVERPAGE_ADDED DI_FLAGS = 0x04000000 // Prop provider added Driver page.
+ DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg
+ DI_OVERRIDE_INFFLAGS DI_FLAGS = 0x10000000 // Override INF flags
+ DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props
+
+ DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs
+
+ DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install
+)
+
+// DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values
+type DI_FLAGSEX uint32
+
+const (
+ DI_FLAGSEX_CI_FAILED DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer
+ DI_FLAGSEX_FINISHINSTALL_ACTION DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context.
+ DI_FLAGSEX_DIDINFOLIST DI_FLAGSEX = 0x00000010 // Did the Class Info List
+ DI_FLAGSEX_DIDCOMPATINFO DI_FLAGSEX = 0x00000020 // Did the Compat Info List
+ DI_FLAGSEX_FILTERCLASSES DI_FLAGSEX = 0x00000040
+ DI_FLAGSEX_SETFAILEDINSTALL DI_FLAGSEX = 0x00000080
+ DI_FLAGSEX_DEVICECHANGE DI_FLAGSEX = 0x00000100
+ DI_FLAGSEX_ALWAYSWRITEIDS DI_FLAGSEX = 0x00000200
+ 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.
+ DI_FLAGSEX_ALLOWEXCLUDEDDRVS DI_FLAGSEX = 0x00000800
+ DI_FLAGSEX_NOUIONQUERYREMOVE DI_FLAGSEX = 0x00001000
+ 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.)
+ DI_FLAGSEX_NO_DRVREG_MODIFY DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key.
+ DI_FLAGSEX_IN_SYSTEM_SETUP DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup.
+ DI_FLAGSEX_INET_DRIVER DI_FLAGSEX = 0x00020000 // Driver came from Windows Update
+ DI_FLAGSEX_APPENDDRIVERLIST DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list.
+ DI_FLAGSEX_PREINSTALLBACKUP DI_FLAGSEX = 0x00080000 // not used
+ DI_FLAGSEX_BACKUPONREPLACE DI_FLAGSEX = 0x00100000 // not used
+ 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)
+ 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.
+ DI_FLAGSEX_POWERPAGE_ADDED DI_FLAGSEX = 0x01000000 // class installer added their own power page
+ DI_FLAGSEX_FILTERSIMILARDRIVERS DI_FLAGSEX = 0x02000000 // only include similar drivers in class list
+ DI_FLAGSEX_INSTALLEDDRIVER DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list. Used in calls to SetupDiBuildDriverInfoList
+ DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list
+ DI_FLAGSEX_ALTPLATFORM_DRVSEARCH DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue
+ 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.
+ DI_FLAGSEX_RECURSIVESEARCH DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search
+ DI_FLAGSEX_SEARCH_PUBLISHED_INFS DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search
+)
+
+// HSPFILEQ is type for setup file queue
+type HSPFILEQ uintptr
+
+type _SP_DEVINSTALL_PARAMS struct {
+ Size uint32
+ Flags DI_FLAGS
+ FlagsEx DI_FLAGSEX
+ hwndParent uintptr
+ InstallMsgHandler uintptr
+ InstallMsgHandlerContext uintptr
+ FileQueue HSPFILEQ
+ _ uintptr
+ _ uint32
+ DriverPath [windows.MAX_PATH]uint16
+}
+
+// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set)
+type DevInstallParams struct {
+ Flags DI_FLAGS
+ FlagsEx DI_FLAGSEX
+ hwndParent uintptr
+ InstallMsgHandler uintptr
+ InstallMsgHandlerContext uintptr
+ FileQueue HSPFILEQ
+ DriverPath string
+}
diff --git a/setupapi/zsetupapi_windows.go b/setupapi/zsetupapi_windows.go
index e8bf8c2..a569219 100644
--- a/setupapi/zsetupapi_windows.go
+++ b/setupapi/zsetupapi_windows.go
@@ -44,6 +44,8 @@ var (
procSetupDiGetDeviceInfoListDetailW = modsetupapi.NewProc("SetupDiGetDeviceInfoListDetailW")
procSetupDiEnumDeviceInfo = modsetupapi.NewProc("SetupDiEnumDeviceInfo")
procSetupDiOpenDevRegKey = modsetupapi.NewProc("SetupDiOpenDevRegKey")
+ procSetupDiGetDeviceInstallParamsW = modsetupapi.NewProc("SetupDiGetDeviceInstallParamsW")
+ procSetupDiSetDeviceInstallParamsW = modsetupapi.NewProc("SetupDiSetDeviceInstallParamsW")
)
func setupDiGetClassDevsEx(ClassGUID *windows.GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, DeviceInfoSet DevInfo, MachineName *uint16, reserved uintptr) (handle DevInfo, err error) {
@@ -107,3 +109,27 @@ func setupDiOpenDevRegKey(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA
}
return
}
+
+func setupDiGetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, DeviceInstallParams *_SP_DEVINSTALL_PARAMS) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInstallParamsW.Addr(), 3, uintptr(DeviceInfoSet), uintptr(unsafe.Pointer(DeviceInfoData)), uintptr(unsafe.Pointer(DeviceInstallParams)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func setupDiSetDeviceInstallParams(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA, DeviceInstallParams *_SP_DEVINSTALL_PARAMS) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetupDiSetDeviceInstallParamsW.Addr(), 3, uintptr(DeviceInfoSet), uintptr(unsafe.Pointer(DeviceInfoData)), uintptr(unsafe.Pointer(DeviceInstallParams)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}