diff --git a/setupapi/setupapi_windows.go b/setupapi/setupapi_windows.go index a48042f..43d0d28 100644 --- a/setupapi/setupapi_windows.go +++ b/setupapi/setupapi_windows.go @@ -227,3 +227,16 @@ func SetupDiClassGuidsFromNameEx(ClassName string, MachineName string) (ClassGui return } + +//sys setupDiGetSelectedDevice(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA) (err error) = setupapi.SetupDiGetSelectedDevice + +// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set. +func SetupDiGetSelectedDevice(DeviceInfoSet DevInfo) (DeviceInfoData *SP_DEVINFO_DATA, err error) { + data := SP_DEVINFO_DATA{} + data.Size = uint32(unsafe.Sizeof(data)) + + return &data, setupDiGetSelectedDevice(DeviceInfoSet, &data) +} + +// 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. +//sys SetupDiSetSelectedDevice(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA) (err error) = setupapi.SetupDiSetSelectedDevice diff --git a/setupapi/setupapi_windows_test.go b/setupapi/setupapi_windows_test.go index 4e07ed2..8d5453f 100644 --- a/setupapi/setupapi_windows_test.go +++ b/setupapi/setupapi_windows_test.go @@ -251,3 +251,42 @@ func TestSetupDiClassGuidsFromNameEx(t *testing.T) { t.Errorf("SetupDiClassGuidsFromNameEx(\"foobar-34274a51-a6e6-45f0-80d6-c62be96dd5fe\") should return an empty GUID set") } } + +func TestSetupDiGetSelectedDevice(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() + + for i := 0; true; i++ { + data, err := SetupDiEnumDeviceInfo(devInfoList, i) + if err != nil { + if errWin, ok := err.(syscall.Errno); ok && errWin == 259 /*ERROR_NO_MORE_ITEMS*/ { + break + } + continue + } + + err = SetupDiSetSelectedDevice(devInfoList, data) + if err != nil { + t.Errorf("Error calling SetupDiSetSelectedDevice: %s", err.Error()) + } + + data2, err := SetupDiGetSelectedDevice(devInfoList) + if err != nil { + t.Errorf("Error calling SetupDiGetSelectedDevice: %s", err.Error()) + } else if *data != *data2 { + t.Error("SetupDiGetSelectedDevice returned different data than was set by SetupDiSetSelectedDevice") + } + } + + err = SetupDiSetSelectedDevice(devInfoList, nil) + if err == nil { + t.Errorf("SetupDiSetSelectedDevice(nil) should fail") + } else { + if errWin, ok := err.(syscall.Errno); !ok || errWin != 87 /*ERROR_INVALID_PARAMETER*/ { + t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER") + } + } +} diff --git a/setupapi/zsetupapi_windows.go b/setupapi/zsetupapi_windows.go index 46a02c4..3a0b441 100644 --- a/setupapi/zsetupapi_windows.go +++ b/setupapi/zsetupapi_windows.go @@ -53,6 +53,8 @@ var ( procSetupDiSetClassInstallParamsW = modsetupapi.NewProc("SetupDiSetClassInstallParamsW") procSetupDiClassNameFromGuidExW = modsetupapi.NewProc("SetupDiClassNameFromGuidExW") procSetupDiClassGuidsFromNameExW = modsetupapi.NewProc("SetupDiClassGuidsFromNameExW") + procSetupDiGetSelectedDevice = modsetupapi.NewProc("SetupDiGetSelectedDevice") + procSetupDiSetSelectedDevice = modsetupapi.NewProc("SetupDiSetSelectedDevice") ) func setupDiCreateDeviceInfoListEx(ClassGUID *windows.GUID, hwndParent uintptr, MachineName *uint16, Reserved uintptr) (handle DevInfo, err error) { @@ -225,3 +227,27 @@ func setupDiClassGuidsFromNameEx(ClassName *uint16, ClassGuidList *windows.GUID, } return } + +func setupDiGetSelectedDevice(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDevice.Addr(), 2, uintptr(DeviceInfoSet), uintptr(unsafe.Pointer(DeviceInfoData)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func SetupDiSetSelectedDevice(DeviceInfoSet DevInfo, DeviceInfoData *SP_DEVINFO_DATA) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDevice.Addr(), 2, uintptr(DeviceInfoSet), uintptr(unsafe.Pointer(DeviceInfoData)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +}