summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-06-10 11:20:49 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-06-10 11:34:59 +0200
commit03eee4a7782ddefa49c682b4de9c13bb5099892c (patch)
tree60421844b9f7482343ec907c25a27404da9116cd
parent700860f8e697b187a7bbd7b226469a1de0818456 (diff)
wintun: add helper for cleaning up
-rw-r--r--tun/wintun/wintun_windows.go91
1 files changed, 82 insertions, 9 deletions
diff --git a/tun/wintun/wintun_windows.go b/tun/wintun/wintun_windows.go
index 7b7a889..9613ffc 100644
--- a/tun/wintun/wintun_windows.go
+++ b/tun/wintun/wintun_windows.go
@@ -114,16 +114,14 @@ func GetInterface(ifname string) (*Wintun, error) {
}
if ifname == strings.ToLower(ifname2) {
- // Interface name found. Check its driver.
- const driverType = setupapi.SPDIT_COMPATDRIVER
- err = devInfoList.BuildDriverInfoList(deviceData, driverType)
+ err = devInfoList.BuildDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
if err != nil {
return nil, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
}
- defer devInfoList.DestroyDriverInfoList(deviceData, driverType)
+ defer devInfoList.DestroyDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
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 == windows.ERROR_NO_MORE_ITEMS {
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)
}
- const driverType = setupapi.SPDIT_COMPATDRIVER
- err = devInfoList.BuildDriverInfoList(deviceData, driverType) // TODO: This takes ~510ms
+ err = devInfoList.BuildDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER) // TODO: This takes ~510ms
if err != nil {
return nil, false, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
}
- defer devInfoList.DestroyDriverInfoList(deviceData, driverType)
+ defer devInfoList.DestroyDriverInfoList(deviceData, setupapi.SPDIT_COMPATDRIVER)
driverDate := windows.Filetime{}
driverVersion := uint64(0)
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 == windows.ERROR_NO_MORE_ITEMS {
break
@@ -419,6 +416,82 @@ func (wintun *Wintun) DeleteInterface() (rebootRequired bool, err error) {
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.
func checkReboot(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfoData) (bool, error) {
devInstallParams, err := deviceInfoSet.DeviceInstallParams(deviceInfoData)