Add support for setupapi.SetupDi(Get|Set)DeviceInstallParams()
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
		
							parent
							
								
									dce5192d86
								
							
						
					
					
						commit
						f1d5db6547
					
				@ -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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user