diff options
author | Simon Rozman <simon@rozman.si> | 2019-03-07 15:19:27 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-03-07 21:12:20 +0100 |
commit | 11f57802506045a137d0e2022bfb16da4fc624f1 (patch) | |
tree | 8efba04077937a091600f3943d285d498e8b1c08 /tun/wintun/setupapi | |
parent | 26af6c4651dbba986c1d05162e9ef1906665da92 (diff) |
wintun: Revise interface creation wait
DIF_INSTALLDEVICE returns almost immediately, while the device
installation continues in the background. It might take a while, before
all registry keys and values are populated.
Previously, wireguard-go waited for HKLM\SYSTEM\CurrentControlSet\
Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\<id> registry key
only.
Followed by a SetInterfaceName() method of Wintun struct which tried to
access HKLM\SYSTEM\CurrentControlSet\Control\Network\
{4D36E972-E325-11CE-BFC1-08002BE10318}\<id>\Connection registry key
might not be available yet.
This commit loops until both registry keys are available before
returning from CreateInterface() function.
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'tun/wintun/setupapi')
-rw-r--r-- | tun/wintun/setupapi/setupapi_windows.go | 29 | ||||
-rw-r--r-- | tun/wintun/setupapi/setupapi_windows_test.go | 5 |
2 files changed, 34 insertions, 0 deletions
diff --git a/tun/wintun/setupapi/setupapi_windows.go b/tun/wintun/setupapi/setupapi_windows.go index 71732a4..5f9e05c 100644 --- a/tun/wintun/setupapi/setupapi_windows.go +++ b/tun/wintun/setupapi/setupapi_windows.go @@ -7,12 +7,14 @@ package setupapi import ( "encoding/binary" + "errors" "fmt" "syscall" "unsafe" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" + "golang.zx2c4.com/wireguard/tun/wintun/guid" ) //sys setupDiCreateDeviceInfoListEx(classGUID *windows.GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(windows.InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW @@ -234,6 +236,33 @@ func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DI return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired) } +// GetInterfaceID method returns network interface ID. +func (deviceInfoSet DevInfo) GetInterfaceID(deviceInfoData *DevInfoData) (*windows.GUID, error) { + // Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key. + key, err := deviceInfoSet.OpenDevRegKey(deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, registry.READ) + if err != nil { + return nil, errors.New("Device-specific registry key open failed: " + err.Error()) + } + defer key.Close() + + // Read the NetCfgInstanceId value. + value, valueType, err := key.GetStringValue("NetCfgInstanceId") + if err != nil { + return nil, errors.New("RegQueryStringValue(\"NetCfgInstanceId\") failed: " + err.Error()) + } + if valueType != registry.SZ { + return nil, fmt.Errorf("NetCfgInstanceId registry value is not REG_SZ (expected: %v, provided: %v)", registry.SZ, valueType) + } + + // Convert to windows.GUID. + ifid, err := guid.FromString(value) + if err != nil { + return nil, fmt.Errorf("NetCfgInstanceId registry value is not a GUID (expected: \"{...}\", provided: \"%v\")", value) + } + + return ifid, nil +} + //sys setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW // SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property. diff --git a/tun/wintun/setupapi/setupapi_windows_test.go b/tun/wintun/setupapi/setupapi_windows_test.go index 30f3692..c6f4a15 100644 --- a/tun/wintun/setupapi/setupapi_windows_test.go +++ b/tun/wintun/setupapi/setupapi_windows_test.go @@ -291,6 +291,11 @@ func TestSetupDiOpenDevRegKey(t *testing.T) { t.Errorf("Error calling SetupDiOpenDevRegKey: %s", err.Error()) } defer key.Close() + + _, err = devInfoList.GetInterfaceID(data) + if err != nil { + t.Errorf("Error calling GetInterfaceID: %s", err.Error()) + } } } |