wintun: add helper for cleaning up

This commit is contained in:
Jason A. Donenfeld 2019-06-10 11:20:49 +02:00
parent 700860f8e6
commit 03eee4a778

View file

@ -114,16 +114,14 @@ func GetInterface(ifname string) (*Wintun, error) {
} }
if ifname == strings.ToLower(ifname2) { if ifname == strings.ToLower(ifname2) {
// Interface name found. Check its driver. err = devInfoList.BuildDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
const driverType = setupapi.SPDIT_COMPATDRIVER
err = devInfoList.BuildDriverInfoList(deviceData, driverType)
if err != nil { if err != nil {
return nil, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err) return nil, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
} }
defer devInfoList.DestroyDriverInfoList(deviceData, driverType) defer devInfoList.DestroyDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
for index := 0; ; index++ { for index := 0; ; index++ {
driverData, err := devInfoList.EnumDriverInfo(deviceData, driverType, index) driverData, err := devInfoList.EnumDriverInfo(deviceData, setupapi.SPDIT_COMPATDRIVER, index)
if err != nil { if err != nil {
if err == windows.ERROR_NO_MORE_ITEMS { if err == windows.ERROR_NO_MORE_ITEMS {
break break
@ -197,17 +195,16 @@ func CreateInterface(description string, requestedGUID *windows.GUID) (wintun *W
return nil, false, fmt.Errorf("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: %v", err) return nil, false, fmt.Errorf("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: %v", err)
} }
const driverType = setupapi.SPDIT_COMPATDRIVER err = devInfoList.BuildDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER) // TODO: This takes ~510ms
err = devInfoList.BuildDriverInfoList(deviceData, driverType) // TODO: This takes ~510ms
if err != nil { if err != nil {
return nil, false, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err) return nil, false, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
} }
defer devInfoList.DestroyDriverInfoList(deviceData, driverType) defer devInfoList.DestroyDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
driverDate := windows.Filetime{} driverDate := windows.Filetime{}
driverVersion := uint64(0) driverVersion := uint64(0)
for index := 0; ; index++ { // TODO: This loop takes ~600ms for index := 0; ; index++ { // TODO: This loop takes ~600ms
driverData, err := devInfoList.EnumDriverInfo(deviceData, driverType, index) driverData, err := devInfoList.EnumDriverInfo(deviceData, setupapi.SPDIT_COMPATDRIVER, index)
if err != nil { if err != nil {
if err == windows.ERROR_NO_MORE_ITEMS { if err == windows.ERROR_NO_MORE_ITEMS {
break break
@ -419,6 +416,82 @@ func (wintun *Wintun) DeleteInterface() (rebootRequired bool, err error) {
return rebootRequired, nil return rebootRequired, nil
} }
// DeleteAllInterfaces deletes all Wintun interfaces, and returns which
// ones it deleted, whether a reboot is required after, and which errors
// occurred during the process.
func DeleteAllInterfaces() (deviceInstancesDeleted []uint32, rebootRequired bool, errors []error) {
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
if err != nil {
return nil, false, []error{fmt.Errorf("SetupDiGetClassDevsEx(%v) failed: %v", deviceClassNetGUID, err.Error())}
}
defer devInfoList.Close()
for i := 0; ; i++ {
deviceData, err := devInfoList.EnumDeviceInfo(i)
if err != nil {
if err == windows.ERROR_NO_MORE_ITEMS {
break
}
continue
}
err = devInfoList.BuildDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
if err != nil {
continue
}
defer devInfoList.DestroyDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
isWintun := false
for j := 0; ; j++ {
driverData, err := devInfoList.EnumDriverInfo(deviceData, setupapi.SPDIT_COMPATDRIVER, j)
if err != nil {
if err == windows.ERROR_NO_MORE_ITEMS {
break
}
continue
}
driverDetailData, err := devInfoList.DriverInfoDetail(deviceData, driverData)
if err != nil {
continue
}
if driverDetailData.IsCompatible(hardwareID) {
isWintun = true
break
}
}
if !isWintun {
continue
}
err = setQuietInstall(devInfoList, deviceData)
if err != nil {
errors = append(errors, err)
continue
}
inst := deviceData.DevInst
removeDeviceParams := setupapi.RemoveDeviceParams{
ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE),
Scope: setupapi.DI_REMOVEDEVICE_GLOBAL,
}
err = devInfoList.SetClassInstallParams(deviceData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams)))
if err != nil {
errors = append(errors, err)
continue
}
err = devInfoList.CallClassInstaller(setupapi.DIF_REMOVE, deviceData)
if err != nil {
errors = append(errors, err)
continue
}
if !rebootRequired {
rebootRequired, _ = checkReboot(devInfoList, deviceData)
}
deviceInstancesDeleted = append(deviceInstancesDeleted, inst)
}
return
}
// checkReboot checks device install parameters if a system reboot is required. // checkReboot checks device install parameters if a system reboot is required.
func checkReboot(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfoData) (bool, error) { func checkReboot(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfoData) (bool, error) {
devInstallParams, err := deviceInfoSet.DeviceInstallParams(deviceInfoData) devInstallParams, err := deviceInfoSet.DeviceInstallParams(deviceInfoData)