]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
wintun: migrate to wintun.dll API
authorSimon Rozman <simon@rozman.si>
Wed, 22 Jul 2020 07:15:49 +0000 (09:15 +0200)
committerSimon Rozman <simon@rozman.si>
Sat, 7 Nov 2020 11:46:35 +0000 (12:46 +0100)
Rather than having every application using Wintun driver reinvent the
wheel, the Wintun device/adapter/interface management has been moved
from wireguard-go to wintun.dll deployed with Wintun itself.

Signed-off-by: Simon Rozman <simon@rozman.si>
25 files changed:
tun/tun_windows.go
tun/wintun/iphlpapi/conversion_windows.go [deleted file]
tun/wintun/iphlpapi/mksyscall.go [deleted file]
tun/wintun/iphlpapi/zsyscall_windows.go [deleted file]
tun/wintun/namespace_windows.go [deleted file]
tun/wintun/namespaceapi/mksyscall.go [deleted file]
tun/wintun/namespaceapi/namespaceapi_windows.go [deleted file]
tun/wintun/namespaceapi/zsyscall_windows.go [deleted file]
tun/wintun/nci/mksyscall.go [deleted file]
tun/wintun/nci/nci_windows.go [deleted file]
tun/wintun/nci/zsyscall_windows.go [deleted file]
tun/wintun/registry/mksyscall.go [deleted file]
tun/wintun/registry/registry_windows.go [deleted file]
tun/wintun/registry/registry_windows_test.go [deleted file]
tun/wintun/registry/zregistry_windows.go [deleted file]
tun/wintun/ring_windows.go
tun/wintun/setupapi/mksyscall.go [deleted file]
tun/wintun/setupapi/setupapi_windows.go [deleted file]
tun/wintun/setupapi/setupapi_windows_test.go [deleted file]
tun/wintun/setupapi/types32_windows.go [deleted file]
tun/wintun/setupapi/types64_windows.go [deleted file]
tun/wintun/setupapi/types_windows.go [deleted file]
tun/wintun/setupapi/zsetupapi_windows.go [deleted file]
tun/wintun/setupapi/zsetupapi_windows_test.go [deleted file]
tun/wintun/wintun_windows.go

index 5a52c56e896797c71d56145dc9894c9af6297686..684d6f0be20610dbcdcd4778adb7580c26a0c878 100644 (file)
@@ -33,7 +33,7 @@ type rateJuggler struct {
 }
 
 type NativeTun struct {
-       wt        *wintun.Interface
+       wt        *wintun.Adapter
        handle    windows.Handle
        close     bool
        events    chan Event
@@ -44,7 +44,15 @@ type NativeTun struct {
        writeLock sync.Mutex
 }
 
-const WintunPool = wintun.Pool("WireGuard")
+var WintunPool *wintun.Pool
+
+func init() {
+       var err error
+       WintunPool, err = wintun.MakePool("WireGuard")
+       if err != nil {
+               panic(fmt.Errorf("Failed to make pool: %v", err))
+       }
+}
 
 //go:linkname procyield runtime.procyield
 func procyield(cycles uint32)
@@ -66,18 +74,18 @@ func CreateTUN(ifname string, mtu int) (Device, error) {
 //
 func CreateTUNWithRequestedGUID(ifname string, requestedGUID *windows.GUID, mtu int) (Device, error) {
        var err error
-       var wt *wintun.Interface
+       var wt *wintun.Adapter
 
        // Does an interface with this name already exist?
-       wt, err = WintunPool.GetInterface(ifname)
+       wt, err = WintunPool.OpenAdapter(ifname)
        if err == nil {
                // If so, we delete it, in case it has weird residual configuration.
-               _, err = wt.DeleteInterface()
+               _, err = wt.Delete(true)
                if err != nil {
                        return nil, fmt.Errorf("Error deleting already existing interface: %v", err)
                }
        }
-       wt, _, err = WintunPool.CreateInterface(ifname, requestedGUID)
+       wt, _, err = WintunPool.CreateAdapter(ifname, requestedGUID)
        if err != nil {
                return nil, fmt.Errorf("Error creating interface: %v", err)
        }
@@ -132,7 +140,7 @@ func (tun *NativeTun) Close() error {
        tun.rings.Close()
        var err error
        if tun.wt != nil {
-               _, err = tun.wt.DeleteInterface()
+               _, err = tun.wt.Delete(false)
        }
        close(tun.events)
        return err
@@ -254,9 +262,9 @@ func (tun *NativeTun) LUID() uint64 {
        return tun.wt.LUID()
 }
 
-// Version returns the version of the Wintun driver and NDIS system currently loaded.
-func (tun *NativeTun) Version() (driverVersion string, ndisVersion string, err error) {
-       return tun.wt.Version()
+// RunningVersion returns the running version of the Wintun driver.
+func (tun *NativeTun) RunningVersion() (version uint32, err error) {
+       return wintun.RunningVersion()
 }
 
 func (rate *rateJuggler) update(packetLen uint64) {
diff --git a/tun/wintun/iphlpapi/conversion_windows.go b/tun/wintun/iphlpapi/conversion_windows.go
deleted file mode 100644 (file)
index d2db8a3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package iphlpapi
-
-import "golang.org/x/sys/windows"
-
-//sys  convertInterfaceLUIDToGUID(interfaceLUID *uint64, interfaceGUID *windows.GUID) (ret error) = iphlpapi.ConvertInterfaceLuidToGuid
-//sys  convertInterfaceAliasToLUID(interfaceAlias *uint16, interfaceLUID *uint64) (ret error) = iphlpapi.ConvertInterfaceAliasToLuid
-
-func InterfaceGUIDFromAlias(alias string) (*windows.GUID, error) {
-       var luid uint64
-       var guid windows.GUID
-       err := convertInterfaceAliasToLUID(windows.StringToUTF16Ptr(alias), &luid)
-       if err != nil {
-               return nil, err
-       }
-       err = convertInterfaceLUIDToGUID(&luid, &guid)
-       if err != nil {
-               return nil, err
-       }
-       return &guid, nil
-}
diff --git a/tun/wintun/iphlpapi/mksyscall.go b/tun/wintun/iphlpapi/mksyscall.go
deleted file mode 100644 (file)
index 8ffc0d4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package iphlpapi
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go conversion_windows.go
diff --git a/tun/wintun/iphlpapi/zsyscall_windows.go b/tun/wintun/iphlpapi/zsyscall_windows.go
deleted file mode 100644 (file)
index dc14294..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package iphlpapi
-
-import (
-       "syscall"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
-       errnoERROR_IO_PENDING = 997
-)
-
-var (
-       errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-       switch e {
-       case 0:
-               return nil
-       case errnoERROR_IO_PENDING:
-               return errERROR_IO_PENDING
-       }
-       // TODO: add more here, after collecting data on the common
-       // error values see on Windows. (perhaps when running
-       // all.bat?)
-       return e
-}
-
-var (
-       modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
-
-       procConvertInterfaceLuidToGuid  = modiphlpapi.NewProc("ConvertInterfaceLuidToGuid")
-       procConvertInterfaceAliasToLuid = modiphlpapi.NewProc("ConvertInterfaceAliasToLuid")
-)
-
-func convertInterfaceLUIDToGUID(interfaceLUID *uint64, interfaceGUID *windows.GUID) (ret error) {
-       r0, _, _ := syscall.Syscall(procConvertInterfaceLuidToGuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceLUID)), uintptr(unsafe.Pointer(interfaceGUID)), 0)
-       if r0 != 0 {
-               ret = syscall.Errno(r0)
-       }
-       return
-}
-
-func convertInterfaceAliasToLUID(interfaceAlias *uint16, interfaceLUID *uint64) (ret error) {
-       r0, _, _ := syscall.Syscall(procConvertInterfaceAliasToLuid.Addr(), 2, uintptr(unsafe.Pointer(interfaceAlias)), uintptr(unsafe.Pointer(interfaceLUID)), 0)
-       if r0 != 0 {
-               ret = syscall.Errno(r0)
-       }
-       return
-}
diff --git a/tun/wintun/namespace_windows.go b/tun/wintun/namespace_windows.go
deleted file mode 100644 (file)
index 302ad45..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package wintun
-
-import (
-       "encoding/hex"
-       "errors"
-       "fmt"
-       "sync"
-       "unsafe"
-
-       "golang.org/x/crypto/blake2s"
-       "golang.org/x/sys/windows"
-       "golang.org/x/text/unicode/norm"
-
-       "golang.zx2c4.com/wireguard/tun/wintun/namespaceapi"
-)
-
-var (
-       wintunObjectSecurityAttributes *windows.SecurityAttributes
-       hasInitializedNamespace        bool
-       initializingNamespace          sync.Mutex
-)
-
-func initializeNamespace() error {
-       initializingNamespace.Lock()
-       defer initializingNamespace.Unlock()
-       if hasInitializedNamespace {
-               return nil
-       }
-       sd, err := windows.SecurityDescriptorFromString("O:SYD:P(A;;GA;;;SY)")
-       if err != nil {
-               return fmt.Errorf("SddlToSecurityDescriptor failed: %v", err)
-       }
-       wintunObjectSecurityAttributes = &windows.SecurityAttributes{
-               Length:             uint32(unsafe.Sizeof(windows.SecurityAttributes{})),
-               SecurityDescriptor: sd,
-       }
-       sid, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
-       if err != nil {
-               return fmt.Errorf("CreateWellKnownSid(LOCAL_SYSTEM) failed: %v", err)
-       }
-
-       boundary, err := namespaceapi.CreateBoundaryDescriptor("Wintun")
-       if err != nil {
-               return fmt.Errorf("CreateBoundaryDescriptor failed: %v", err)
-       }
-       err = boundary.AddSid(sid)
-       if err != nil {
-               return fmt.Errorf("AddSIDToBoundaryDescriptor failed: %v", err)
-       }
-       for {
-               _, err = namespaceapi.CreatePrivateNamespace(wintunObjectSecurityAttributes, boundary, "Wintun")
-               if err == windows.ERROR_ALREADY_EXISTS {
-                       _, err = namespaceapi.OpenPrivateNamespace(boundary, "Wintun")
-                       if err == windows.ERROR_PATH_NOT_FOUND {
-                               continue
-                       }
-                       if err != nil {
-                               return fmt.Errorf("OpenPrivateNamespace failed: %v", err)
-                       }
-               }
-               if err != nil {
-                       return fmt.Errorf("CreatePrivateNamespace failed: %v", err)
-               }
-               break
-       }
-       hasInitializedNamespace = true
-       return nil
-}
-
-func (pool Pool) takeNameMutex() (windows.Handle, error) {
-       err := initializeNamespace()
-       if err != nil {
-               return 0, err
-       }
-
-       const mutexLabel = "WireGuard Adapter Name Mutex Stable Suffix v1 jason@zx2c4.com"
-       b2, _ := blake2s.New256(nil)
-       b2.Write([]byte(mutexLabel))
-       b2.Write(norm.NFC.Bytes([]byte(string(pool))))
-       mutexName := `Wintun\Wintun-Name-Mutex-` + hex.EncodeToString(b2.Sum(nil))
-       mutex, err := windows.CreateMutex(wintunObjectSecurityAttributes, false, windows.StringToUTF16Ptr(mutexName))
-       if err != nil {
-               err = fmt.Errorf("Error creating name mutex: %v", err)
-               return 0, err
-       }
-       event, err := windows.WaitForSingleObject(mutex, windows.INFINITE)
-       if err != nil {
-               windows.CloseHandle(mutex)
-               return 0, fmt.Errorf("Error waiting on name mutex: %v", err)
-       }
-       if event != windows.WAIT_OBJECT_0 && event != windows.WAIT_ABANDONED {
-               windows.CloseHandle(mutex)
-               return 0, errors.New("Error with event trigger of name mutex")
-       }
-       return mutex, nil
-}
diff --git a/tun/wintun/namespaceapi/mksyscall.go b/tun/wintun/namespaceapi/mksyscall.go
deleted file mode 100644 (file)
index 8ea3085..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package namespaceapi
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go namespaceapi_windows.go
diff --git a/tun/wintun/namespaceapi/namespaceapi_windows.go b/tun/wintun/namespaceapi/namespaceapi_windows.go
deleted file mode 100644 (file)
index e71077c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package namespaceapi
-
-import "golang.org/x/sys/windows"
-
-//sys  createBoundaryDescriptor(name *uint16, flags uint32) (handle windows.Handle, err error) = kernel32.CreateBoundaryDescriptorW
-//sys  deleteBoundaryDescriptor(boundaryDescriptor windows.Handle) = kernel32.DeleteBoundaryDescriptor
-//sys  addSIDToBoundaryDescriptor(boundaryDescriptor *windows.Handle, requiredSid *windows.SID) (err error) = kernel32.AddSIDToBoundaryDescriptor
-//sys  createPrivateNamespace(privateNamespaceAttributes *windows.SecurityAttributes, boundaryDescriptor windows.Handle, aliasPrefix *uint16) (handle windows.Handle, err error) = kernel32.CreatePrivateNamespaceW
-//sys  openPrivateNamespace(boundaryDescriptor windows.Handle, aliasPrefix *uint16) (handle windows.Handle, err error) = kernel32.OpenPrivateNamespaceW
-//sys  closePrivateNamespace(handle windows.Handle, flags uint32) (err error) = kernel32.ClosePrivateNamespace
-
-// BoundaryDescriptor represents a boundary that defines how the objects in the namespace are to be isolated.
-type BoundaryDescriptor windows.Handle
-
-// CreateBoundaryDescriptor creates a boundary descriptor.
-func CreateBoundaryDescriptor(name string) (BoundaryDescriptor, error) {
-       name16, err := windows.UTF16PtrFromString(name)
-       if err != nil {
-               return 0, err
-       }
-       handle, err := createBoundaryDescriptor(name16, 0)
-       if err != nil {
-               return 0, err
-       }
-       return BoundaryDescriptor(handle), nil
-}
-
-// Delete deletes the specified boundary descriptor.
-func (bd BoundaryDescriptor) Delete() {
-       deleteBoundaryDescriptor(windows.Handle(bd))
-}
-
-// AddSid adds a security identifier (SID) to the specified boundary descriptor.
-func (bd *BoundaryDescriptor) AddSid(requiredSid *windows.SID) error {
-       return addSIDToBoundaryDescriptor((*windows.Handle)(bd), requiredSid)
-}
-
-// PrivateNamespace represents a private namespace.
-type PrivateNamespace windows.Handle
-
-// CreatePrivateNamespace creates a private namespace.
-func CreatePrivateNamespace(privateNamespaceAttributes *windows.SecurityAttributes, boundaryDescriptor BoundaryDescriptor, aliasPrefix string) (PrivateNamespace, error) {
-       aliasPrefix16, err := windows.UTF16PtrFromString(aliasPrefix)
-       if err != nil {
-               return 0, err
-       }
-       handle, err := createPrivateNamespace(privateNamespaceAttributes, windows.Handle(boundaryDescriptor), aliasPrefix16)
-       if err != nil {
-               return 0, err
-       }
-       return PrivateNamespace(handle), nil
-}
-
-// OpenPrivateNamespace opens a private namespace.
-func OpenPrivateNamespace(boundaryDescriptor BoundaryDescriptor, aliasPrefix string) (PrivateNamespace, error) {
-       aliasPrefix16, err := windows.UTF16PtrFromString(aliasPrefix)
-       if err != nil {
-               return 0, err
-       }
-       handle, err := openPrivateNamespace(windows.Handle(boundaryDescriptor), aliasPrefix16)
-       if err != nil {
-               return 0, err
-       }
-       return PrivateNamespace(handle), nil
-}
-
-// ClosePrivateNamespaceFlags describes flags that are used by PrivateNamespace's Close() method.
-type ClosePrivateNamespaceFlags uint32
-
-const (
-       // PrivateNamespaceFlagDestroy makes the close to destroy the namespace.
-       PrivateNamespaceFlagDestroy = ClosePrivateNamespaceFlags(0x1)
-)
-
-// Close closes an open namespace handle.
-func (pns PrivateNamespace) Close(flags ClosePrivateNamespaceFlags) error {
-       return closePrivateNamespace(windows.Handle(pns), uint32(flags))
-}
diff --git a/tun/wintun/namespaceapi/zsyscall_windows.go b/tun/wintun/namespaceapi/zsyscall_windows.go
deleted file mode 100644 (file)
index 508c223..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package namespaceapi
-
-import (
-       "syscall"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
-       errnoERROR_IO_PENDING = 997
-)
-
-var (
-       errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-       switch e {
-       case 0:
-               return nil
-       case errnoERROR_IO_PENDING:
-               return errERROR_IO_PENDING
-       }
-       // TODO: add more here, after collecting data on the common
-       // error values see on Windows. (perhaps when running
-       // all.bat?)
-       return e
-}
-
-var (
-       modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
-
-       procCreateBoundaryDescriptorW  = modkernel32.NewProc("CreateBoundaryDescriptorW")
-       procDeleteBoundaryDescriptor   = modkernel32.NewProc("DeleteBoundaryDescriptor")
-       procAddSIDToBoundaryDescriptor = modkernel32.NewProc("AddSIDToBoundaryDescriptor")
-       procCreatePrivateNamespaceW    = modkernel32.NewProc("CreatePrivateNamespaceW")
-       procOpenPrivateNamespaceW      = modkernel32.NewProc("OpenPrivateNamespaceW")
-       procClosePrivateNamespace      = modkernel32.NewProc("ClosePrivateNamespace")
-)
-
-func createBoundaryDescriptor(name *uint16, flags uint32) (handle windows.Handle, err error) {
-       r0, _, e1 := syscall.Syscall(procCreateBoundaryDescriptorW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0)
-       handle = windows.Handle(r0)
-       if handle == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func deleteBoundaryDescriptor(boundaryDescriptor windows.Handle) {
-       syscall.Syscall(procDeleteBoundaryDescriptor.Addr(), 1, uintptr(boundaryDescriptor), 0, 0)
-       return
-}
-
-func addSIDToBoundaryDescriptor(boundaryDescriptor *windows.Handle, requiredSid *windows.SID) (err error) {
-       r1, _, e1 := syscall.Syscall(procAddSIDToBoundaryDescriptor.Addr(), 2, uintptr(unsafe.Pointer(boundaryDescriptor)), uintptr(unsafe.Pointer(requiredSid)), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func createPrivateNamespace(privateNamespaceAttributes *windows.SecurityAttributes, boundaryDescriptor windows.Handle, aliasPrefix *uint16) (handle windows.Handle, err error) {
-       r0, _, e1 := syscall.Syscall(procCreatePrivateNamespaceW.Addr(), 3, uintptr(unsafe.Pointer(privateNamespaceAttributes)), uintptr(boundaryDescriptor), uintptr(unsafe.Pointer(aliasPrefix)))
-       handle = windows.Handle(r0)
-       if handle == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func openPrivateNamespace(boundaryDescriptor windows.Handle, aliasPrefix *uint16) (handle windows.Handle, err error) {
-       r0, _, e1 := syscall.Syscall(procOpenPrivateNamespaceW.Addr(), 2, uintptr(boundaryDescriptor), uintptr(unsafe.Pointer(aliasPrefix)), 0)
-       handle = windows.Handle(r0)
-       if handle == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func closePrivateNamespace(handle windows.Handle, flags uint32) (err error) {
-       r1, _, e1 := syscall.Syscall(procClosePrivateNamespace.Addr(), 2, uintptr(handle), uintptr(flags), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
diff --git a/tun/wintun/nci/mksyscall.go b/tun/wintun/nci/mksyscall.go
deleted file mode 100644 (file)
index 129e015..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package nci
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go nci_windows.go
diff --git a/tun/wintun/nci/nci_windows.go b/tun/wintun/nci/nci_windows.go
deleted file mode 100644 (file)
index dc9733c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package nci
-
-import "golang.org/x/sys/windows"
-
-//sys  nciSetConnectionName(guid *windows.GUID, newName *uint16) (ret error) = nci.NciSetConnectionName
-//sys  nciGetConnectionName(guid *windows.GUID, destName *uint16, inDestNameBytes uint32, outDestNameBytes *uint32) (ret error) = nci.NciGetConnectionName
-
-func SetConnectionName(guid *windows.GUID, newName string) error {
-       newName16, err := windows.UTF16PtrFromString(newName)
-       if err != nil {
-               return err
-       }
-       return nciSetConnectionName(guid, newName16)
-}
-
-func ConnectionName(guid *windows.GUID) (string, error) {
-       var name [0x400]uint16
-       err := nciGetConnectionName(guid, &name[0], uint32(len(name)*2), nil)
-       if err != nil {
-               return "", err
-       }
-       return windows.UTF16ToString(name[:]), nil
-}
diff --git a/tun/wintun/nci/zsyscall_windows.go b/tun/wintun/nci/zsyscall_windows.go
deleted file mode 100644 (file)
index 2a7b79e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package nci
-
-import (
-       "syscall"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
-       errnoERROR_IO_PENDING = 997
-)
-
-var (
-       errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-       switch e {
-       case 0:
-               return nil
-       case errnoERROR_IO_PENDING:
-               return errERROR_IO_PENDING
-       }
-       // TODO: add more here, after collecting data on the common
-       // error values see on Windows. (perhaps when running
-       // all.bat?)
-       return e
-}
-
-var (
-       modnci = windows.NewLazySystemDLL("nci.dll")
-
-       procNciSetConnectionName = modnci.NewProc("NciSetConnectionName")
-       procNciGetConnectionName = modnci.NewProc("NciGetConnectionName")
-)
-
-func nciSetConnectionName(guid *windows.GUID, newName *uint16) (ret error) {
-       r0, _, _ := syscall.Syscall(procNciSetConnectionName.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(newName)), 0)
-       if r0 != 0 {
-               ret = syscall.Errno(r0)
-       }
-       return
-}
-
-func nciGetConnectionName(guid *windows.GUID, destName *uint16, inDestNameBytes uint32, outDestNameBytes *uint32) (ret error) {
-       r0, _, _ := syscall.Syscall6(procNciGetConnectionName.Addr(), 4, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(destName)), uintptr(inDestNameBytes), uintptr(unsafe.Pointer(outDestNameBytes)), 0, 0)
-       if r0 != 0 {
-               ret = syscall.Errno(r0)
-       }
-       return
-}
diff --git a/tun/wintun/registry/mksyscall.go b/tun/wintun/registry/mksyscall.go
deleted file mode 100644 (file)
index 3e9ff1f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package registry
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zregistry_windows.go registry_windows.go
diff --git a/tun/wintun/registry/registry_windows.go b/tun/wintun/registry/registry_windows.go
deleted file mode 100644 (file)
index 70419a5..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package registry
-
-import (
-       "errors"
-       "fmt"
-       "runtime"
-       "strings"
-       "time"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-       "golang.org/x/sys/windows/registry"
-)
-
-const (
-       // REG_NOTIFY_CHANGE_NAME notifies the caller if a subkey is added or deleted.
-       REG_NOTIFY_CHANGE_NAME uint32 = 0x00000001
-
-       // REG_NOTIFY_CHANGE_ATTRIBUTES notifies the caller of changes to the attributes of the key, such as the security descriptor information.
-       REG_NOTIFY_CHANGE_ATTRIBUTES uint32 = 0x00000002
-
-       // REG_NOTIFY_CHANGE_LAST_SET notifies the caller of changes to a value of the key. This can include adding or deleting a value, or changing an existing value.
-       REG_NOTIFY_CHANGE_LAST_SET uint32 = 0x00000004
-
-       // REG_NOTIFY_CHANGE_SECURITY notifies the caller of changes to the security descriptor of the key.
-       REG_NOTIFY_CHANGE_SECURITY uint32 = 0x00000008
-
-       // REG_NOTIFY_THREAD_AGNOSTIC indicates that the lifetime of the registration must not be tied to the lifetime of the thread issuing the RegNotifyChangeKeyValue call. Note: This flag value is only supported in Windows 8 and later.
-       REG_NOTIFY_THREAD_AGNOSTIC uint32 = 0x10000000
-)
-
-//sys  regNotifyChangeKeyValue(key windows.Handle, watchSubtree bool, notifyFilter uint32, event windows.Handle, asynchronous bool) (regerrno error) = advapi32.RegNotifyChangeKeyValue
-
-func OpenKeyWait(k registry.Key, path string, access uint32, timeout time.Duration) (registry.Key, error) {
-       runtime.LockOSThread()
-       defer runtime.UnlockOSThread()
-
-       deadline := time.Now().Add(timeout)
-       pathSpl := strings.Split(path, "\\")
-       for i := 0; ; i++ {
-               keyName := pathSpl[i]
-               isLast := i+1 == len(pathSpl)
-
-               event, err := windows.CreateEvent(nil, 0, 0, nil)
-               if err != nil {
-                       return 0, fmt.Errorf("Error creating event: %v", err)
-               }
-               defer windows.CloseHandle(event)
-
-               var key registry.Key
-               for {
-                       err = regNotifyChangeKeyValue(windows.Handle(k), false, REG_NOTIFY_CHANGE_NAME, windows.Handle(event), true)
-                       if err != nil {
-                               return 0, fmt.Errorf("Setting up change notification on registry key failed: %v", err)
-                       }
-
-                       var accessFlags uint32
-                       if isLast {
-                               accessFlags = access
-                       } else {
-                               accessFlags = registry.NOTIFY
-                       }
-                       key, err = registry.OpenKey(k, keyName, accessFlags)
-                       if err == windows.ERROR_FILE_NOT_FOUND || err == windows.ERROR_PATH_NOT_FOUND {
-                               timeout := time.Until(deadline) / time.Millisecond
-                               if timeout < 0 {
-                                       timeout = 0
-                               }
-                               s, err := windows.WaitForSingleObject(event, uint32(timeout))
-                               if err != nil {
-                                       return 0, fmt.Errorf("Unable to wait on registry key: %v", err)
-                               }
-                               if s == uint32(windows.WAIT_TIMEOUT) { // windows.WAIT_TIMEOUT status const is misclassified as error in golang.org/x/sys/windows
-                                       return 0, errors.New("Timeout waiting for registry key")
-                               }
-                       } else if err != nil {
-                               return 0, fmt.Errorf("Error opening registry key %v: %v", path, err)
-                       } else {
-                               if isLast {
-                                       return key, nil
-                               }
-                               defer key.Close()
-                               break
-                       }
-               }
-
-               k = key
-       }
-}
-
-func WaitForKey(k registry.Key, path string, timeout time.Duration) error {
-       key, err := OpenKeyWait(k, path, registry.NOTIFY, timeout)
-       if err != nil {
-               return err
-       }
-       key.Close()
-       return nil
-}
-
-//
-// getValue is more or less the same as windows/registry's getValue.
-//
-func getValue(k registry.Key, name string, buf []byte) (value []byte, valueType uint32, err error) {
-       var name16 *uint16
-       name16, err = windows.UTF16PtrFromString(name)
-       if err != nil {
-               return
-       }
-       n := uint32(len(buf))
-       for {
-               err = windows.RegQueryValueEx(windows.Handle(k), name16, nil, &valueType, (*byte)(unsafe.Pointer(&buf[0])), &n)
-               if err == nil {
-                       value = buf[:n]
-                       return
-               }
-               if err != windows.ERROR_MORE_DATA {
-                       return
-               }
-               if n <= uint32(len(buf)) {
-                       return
-               }
-               buf = make([]byte, n)
-       }
-}
-
-//
-// getValueRetry function reads any value from registry. It waits for
-// the registry value to become available or returns error on timeout.
-//
-// Key must be opened with at least QUERY_VALUE|NOTIFY access.
-//
-func getValueRetry(key registry.Key, name string, buf []byte, timeout time.Duration) ([]byte, uint32, error) {
-       runtime.LockOSThread()
-       defer runtime.UnlockOSThread()
-
-       event, err := windows.CreateEvent(nil, 0, 0, nil)
-       if err != nil {
-               return nil, 0, fmt.Errorf("Error creating event: %v", err)
-       }
-       defer windows.CloseHandle(event)
-
-       deadline := time.Now().Add(timeout)
-       for {
-               err := regNotifyChangeKeyValue(windows.Handle(key), false, REG_NOTIFY_CHANGE_LAST_SET, windows.Handle(event), true)
-               if err != nil {
-                       return nil, 0, fmt.Errorf("Setting up change notification on registry value failed: %v", err)
-               }
-
-               buf, valueType, err := getValue(key, name, buf)
-               if err == windows.ERROR_FILE_NOT_FOUND || err == windows.ERROR_PATH_NOT_FOUND {
-                       timeout := time.Until(deadline) / time.Millisecond
-                       if timeout < 0 {
-                               timeout = 0
-                       }
-                       s, err := windows.WaitForSingleObject(event, uint32(timeout))
-                       if err != nil {
-                               return nil, 0, fmt.Errorf("Unable to wait on registry value: %v", err)
-                       }
-                       if s == uint32(windows.WAIT_TIMEOUT) { // windows.WAIT_TIMEOUT status const is misclassified as error in golang.org/x/sys/windows
-                               return nil, 0, errors.New("Timeout waiting for registry value")
-                       }
-               } else if err != nil {
-                       return nil, 0, fmt.Errorf("Error reading registry value %v: %v", name, err)
-               } else {
-                       return buf, valueType, nil
-               }
-       }
-}
-
-func toString(buf []byte, valueType uint32, err error) (string, error) {
-       if err != nil {
-               return "", err
-       }
-
-       var value string
-       switch valueType {
-       case registry.SZ, registry.EXPAND_SZ, registry.MULTI_SZ:
-               if len(buf) == 0 {
-                       return "", nil
-               }
-               value = windows.UTF16PtrToString((*uint16)(unsafe.Pointer(&buf[0])))
-
-       default:
-               return "", registry.ErrUnexpectedType
-       }
-
-       if valueType != registry.EXPAND_SZ {
-               // Value does not require expansion.
-               return value, nil
-       }
-
-       valueExp, err := registry.ExpandString(value)
-       if err != nil {
-               // Expanding failed: return original sting value.
-               return value, nil
-       }
-
-       // Return expanded value.
-       return valueExp, nil
-}
-
-func toInteger(buf []byte, valueType uint32, err error) (uint64, error) {
-       if err != nil {
-               return 0, err
-       }
-
-       switch valueType {
-       case registry.DWORD:
-               if len(buf) != 4 {
-                       return 0, errors.New("DWORD value is not 4 bytes long")
-               }
-               var val uint32
-               copy((*[4]byte)(unsafe.Pointer(&val))[:], buf)
-               return uint64(val), nil
-
-       case registry.QWORD:
-               if len(buf) != 8 {
-                       return 0, errors.New("QWORD value is not 8 bytes long")
-               }
-               var val uint64
-               copy((*[8]byte)(unsafe.Pointer(&val))[:], buf)
-               return val, nil
-
-       default:
-               return 0, registry.ErrUnexpectedType
-       }
-}
-
-//
-// GetStringValueWait function reads a string value from registry. It waits
-// for the registry value to become available or returns error on timeout.
-//
-// Key must be opened with at least QUERY_VALUE|NOTIFY access.
-//
-// If the value type is REG_EXPAND_SZ the environment variables are expanded.
-// Should expanding fail, original string value and nil error are returned.
-//
-// If the value type is REG_MULTI_SZ only the first string is returned.
-//
-func GetStringValueWait(key registry.Key, name string, timeout time.Duration) (string, error) {
-       return toString(getValueRetry(key, name, make([]byte, 256), timeout))
-}
-
-//
-// GetStringValue function reads a string value from registry.
-//
-// Key must be opened with at least QUERY_VALUE access.
-//
-// If the value type is REG_EXPAND_SZ the environment variables are expanded.
-// Should expanding fail, original string value and nil error are returned.
-//
-// If the value type is REG_MULTI_SZ only the first string is returned.
-//
-func GetStringValue(key registry.Key, name string) (string, error) {
-       return toString(getValue(key, name, make([]byte, 256)))
-}
-
-//
-// GetIntegerValueWait function reads a DWORD32 or QWORD value from registry.
-// It waits for the registry value to become available or returns error on
-// timeout.
-//
-// Key must be opened with at least QUERY_VALUE|NOTIFY access.
-//
-func GetIntegerValueWait(key registry.Key, name string, timeout time.Duration) (uint64, error) {
-       return toInteger(getValueRetry(key, name, make([]byte, 8), timeout))
-}
diff --git a/tun/wintun/registry/registry_windows_test.go b/tun/wintun/registry/registry_windows_test.go
deleted file mode 100644 (file)
index 2479b3d..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package registry
-
-import (
-       "testing"
-       "time"
-
-       "golang.org/x/sys/windows/registry"
-)
-
-const keyRoot = registry.CURRENT_USER
-const pathRoot = "Software\\WireGuardRegistryTest"
-const path = pathRoot + "\\foobar"
-const pathFake = pathRoot + "\\raboof"
-
-func Test_WaitForKey(t *testing.T) {
-       registry.DeleteKey(keyRoot, path)
-       registry.DeleteKey(keyRoot, pathRoot)
-       go func() {
-               time.Sleep(time.Second * 1)
-               key, _, err := registry.CreateKey(keyRoot, pathFake, registry.QUERY_VALUE)
-               if err != nil {
-                       t.Errorf("Error creating registry key: %v", err)
-               }
-               key.Close()
-               registry.DeleteKey(keyRoot, pathFake)
-
-               key, _, err = registry.CreateKey(keyRoot, path, registry.QUERY_VALUE)
-               if err != nil {
-                       t.Errorf("Error creating registry key: %v", err)
-               }
-               key.Close()
-       }()
-       err := WaitForKey(keyRoot, path, time.Second*2)
-       if err != nil {
-               t.Errorf("Error waiting for registry key: %v", err)
-       }
-       registry.DeleteKey(keyRoot, path)
-       registry.DeleteKey(keyRoot, pathRoot)
-
-       err = WaitForKey(keyRoot, path, time.Second*1)
-       if err == nil {
-               t.Error("Registry key notification expected to timeout but it succeeded.")
-       }
-}
-
-func Test_GetValueWait(t *testing.T) {
-       registry.DeleteKey(keyRoot, path)
-       registry.DeleteKey(keyRoot, pathRoot)
-       go func() {
-               time.Sleep(time.Second * 1)
-               key, _, err := registry.CreateKey(keyRoot, path, registry.SET_VALUE)
-               if err != nil {
-                       t.Errorf("Error creating registry key: %v", err)
-               }
-               time.Sleep(time.Second * 1)
-               key.SetStringValue("name1", "eulav")
-               key.SetExpandStringValue("name2", "value")
-               time.Sleep(time.Second * 1)
-               key.SetDWordValue("name3", ^uint32(123))
-               key.SetDWordValue("name4", 123)
-               key.Close()
-       }()
-
-       key, err := OpenKeyWait(keyRoot, path, registry.QUERY_VALUE|registry.NOTIFY, time.Second*2)
-       if err != nil {
-               t.Errorf("Error waiting for registry key: %v", err)
-       }
-
-       valueStr, err := GetStringValueWait(key, "name2", time.Second*2)
-       if err != nil {
-               t.Errorf("Error waiting for registry value: %v", err)
-       }
-       if valueStr != "value" {
-               t.Errorf("Wrong value read: %v", valueStr)
-       }
-
-       _, err = GetStringValueWait(key, "nonexisting", time.Second*1)
-       if err == nil {
-               t.Error("Registry value notification expected to timeout but it succeeded.")
-       }
-
-       valueInt, err := GetIntegerValueWait(key, "name4", time.Second*2)
-       if err != nil {
-               t.Errorf("Error waiting for registry value: %v", err)
-       }
-       if valueInt != 123 {
-               t.Errorf("Wrong value read: %v", valueInt)
-       }
-
-       _, err = GetIntegerValueWait(key, "nonexisting", time.Second*1)
-       if err == nil {
-               t.Error("Registry value notification expected to timeout but it succeeded.")
-       }
-
-       key.Close()
-       registry.DeleteKey(keyRoot, path)
-       registry.DeleteKey(keyRoot, pathRoot)
-}
diff --git a/tun/wintun/registry/zregistry_windows.go b/tun/wintun/registry/zregistry_windows.go
deleted file mode 100644 (file)
index f7ac33b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package registry
-
-import (
-       "syscall"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
-       errnoERROR_IO_PENDING = 997
-)
-
-var (
-       errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-       switch e {
-       case 0:
-               return nil
-       case errnoERROR_IO_PENDING:
-               return errERROR_IO_PENDING
-       }
-       // TODO: add more here, after collecting data on the common
-       // error values see on Windows. (perhaps when running
-       // all.bat?)
-       return e
-}
-
-var (
-       modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
-
-       procRegNotifyChangeKeyValue = modadvapi32.NewProc("RegNotifyChangeKeyValue")
-)
-
-func regNotifyChangeKeyValue(key windows.Handle, watchSubtree bool, notifyFilter uint32, event windows.Handle, asynchronous bool) (regerrno error) {
-       var _p0 uint32
-       if watchSubtree {
-               _p0 = 1
-       } else {
-               _p0 = 0
-       }
-       var _p1 uint32
-       if asynchronous {
-               _p1 = 1
-       } else {
-               _p1 = 0
-       }
-       r0, _, _ := syscall.Syscall6(procRegNotifyChangeKeyValue.Addr(), 5, uintptr(key), uintptr(_p0), uintptr(notifyFilter), uintptr(event), uintptr(_p1), 0)
-       if r0 != 0 {
-               regerrno = syscall.Errno(r0)
-       }
-       return
-}
index 4d2fab667fc8cf604bcd218e617ffb83f8d92266..ed460fb16b67f3906e72cda10194770af1c3530f 100644 (file)
@@ -103,8 +103,8 @@ func (descriptor *RingDescriptor) Close() {
        }
 }
 
-func (wintun *Interface) Register(descriptor *RingDescriptor) (windows.Handle, error) {
-       handle, err := wintun.handle()
+func (wintun *Adapter) Register(descriptor *RingDescriptor) (windows.Handle, error) {
+       handle, err := wintun.OpenAdapterDeviceObject()
        if err != nil {
                return 0, err
        }
diff --git a/tun/wintun/setupapi/mksyscall.go b/tun/wintun/setupapi/mksyscall.go
deleted file mode 100644 (file)
index 234851c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsetupapi_windows.go setupapi_windows.go
diff --git a/tun/wintun/setupapi/setupapi_windows.go b/tun/wintun/setupapi/setupapi_windows.go
deleted file mode 100644 (file)
index a804dd8..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-import (
-       "encoding/binary"
-       "fmt"
-       "runtime"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-       "golang.org/x/sys/windows/registry"
-)
-
-//sys  setupDiCreateDeviceInfoListEx(classGUID *windows.GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(windows.InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW
-
-// SetupDiCreateDeviceInfoListEx function creates an empty device information set on a remote or a local computer and optionally associates the set with a device setup class.
-func SetupDiCreateDeviceInfoListEx(classGUID *windows.GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) {
-       var machineNameUTF16 *uint16
-       if machineName != "" {
-               machineNameUTF16, err = windows.UTF16PtrFromString(machineName)
-               if err != nil {
-                       return
-               }
-       }
-       return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0)
-}
-
-//sys  setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW
-
-// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
-func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) {
-       data := &DevInfoListDetailData{}
-       data.size = sizeofDevInfoListDetailData
-
-       return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data)
-}
-
-// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name.
-func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) {
-       return SetupDiGetDeviceInfoListDetail(deviceInfoSet)
-}
-
-//sys  setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *windows.GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW
-
-// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set.
-func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *windows.GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) {
-       deviceNameUTF16, err := windows.UTF16PtrFromString(deviceName)
-       if err != nil {
-               return
-       }
-
-       var deviceDescriptionUTF16 *uint16
-       if deviceDescription != "" {
-               deviceDescriptionUTF16, err = windows.UTF16PtrFromString(deviceDescription)
-               if err != nil {
-                       return
-               }
-       }
-
-       data := &DevInfoData{}
-       data.size = uint32(unsafe.Sizeof(*data))
-
-       return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data)
-}
-
-// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set.
-func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *windows.GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) {
-       return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags)
-}
-
-//sys  setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo
-
-// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set.
-func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) {
-       data := &DevInfoData{}
-       data.size = uint32(unsafe.Sizeof(*data))
-
-       return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data)
-}
-
-// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set.
-func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) {
-       return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex)
-}
-
-// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.
-//sys  SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList
-
-// Close method deletes a device information set and frees all associated memory.
-func (deviceInfoSet DevInfo) Close() error {
-       return SetupDiDestroyDeviceInfoList(deviceInfoSet)
-}
-
-//sys  SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList
-
-// BuildDriverInfoList method builds a list of drivers that is associated with a specific device or with the global class driver list for a device information set.
-func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
-       return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
-}
-
-//sys  SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch
-
-// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread.
-func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error {
-       return SetupDiCancelDriverInfoSearch(deviceInfoSet)
-}
-
-//sys  setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW
-
-// SetupDiEnumDriverInfo function enumerates the members of a driver list.
-func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
-       data := &DrvInfoData{}
-       data.size = uint32(unsafe.Sizeof(*data))
-
-       return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data)
-}
-
-// EnumDriverInfo method enumerates the members of a driver list.
-func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) {
-       return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex)
-}
-
-//sys  setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW
-
-// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element.
-func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) {
-       data := &DrvInfoData{}
-       data.size = uint32(unsafe.Sizeof(*data))
-
-       return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data)
-}
-
-// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element.
-func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) {
-       return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData)
-}
-
-//sys  SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW
-
-// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set.
-func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error {
-       return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData)
-}
-
-//sys  setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW
-
-// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set.
-func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
-       reqSize := uint32(2048)
-       for {
-               buf := make([]byte, reqSize)
-               data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0]))
-               data.size = sizeofDrvInfoDetailData
-               err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize)
-               if err == windows.ERROR_INSUFFICIENT_BUFFER {
-                       continue
-               }
-               if err != nil {
-                       return nil, err
-               }
-               data.size = reqSize
-               return data, nil
-       }
-}
-
-// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set.
-func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) {
-       return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData)
-}
-
-//sys  SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList
-
-// DestroyDriverInfoList method deletes a driver list.
-func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error {
-       return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType)
-}
-
-//sys  setupDiGetClassDevsEx(classGUID *windows.GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(windows.InvalidHandle)] = setupapi.SetupDiGetClassDevsExW
-
-// 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) {
-       var enumeratorUTF16 *uint16
-       if enumerator != "" {
-               enumeratorUTF16, err = windows.UTF16PtrFromString(enumerator)
-               if err != nil {
-                       return
-               }
-       }
-       var machineNameUTF16 *uint16
-       if machineName != "" {
-               machineNameUTF16, err = windows.UTF16PtrFromString(machineName)
-               if err != nil {
-                       return
-               }
-       }
-       return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0)
-}
-
-// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
-//sys  SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller
-
-// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code).
-func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error {
-       return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData)
-}
-
-//sys  setupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key windows.Handle, err error) [failretval==windows.InvalidHandle] = setupapi.SetupDiOpenDevRegKey
-
-// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information.
-func SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, scope DICS_FLAG, hwProfile uint32, keyType DIREG, samDesired uint32) (registry.Key, error) {
-       handle, err := setupDiOpenDevRegKey(deviceInfoSet, deviceInfoData, scope, hwProfile, keyType, samDesired)
-       return registry.Key(handle), err
-}
-
-// OpenDevRegKey method opens a registry key for device-specific configuration information.
-func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (registry.Key, error) {
-       return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired)
-}
-
-//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.
-func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) {
-       reqSize := uint32(256)
-       for {
-               var dataType uint32
-               buf := make([]byte, reqSize)
-               err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize)
-               if err == windows.ERROR_INSUFFICIENT_BUFFER {
-                       continue
-               }
-               if err != nil {
-                       return
-               }
-               return getRegistryValue(buf[:reqSize], dataType)
-       }
-}
-
-func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
-       switch dataType {
-       case windows.REG_SZ:
-               ret := windows.UTF16ToString(bufToUTF16(buf))
-               runtime.KeepAlive(buf)
-               return ret, nil
-       case windows.REG_EXPAND_SZ:
-               ret, err := registry.ExpandString(windows.UTF16ToString(bufToUTF16(buf)))
-               runtime.KeepAlive(buf)
-               return ret, err
-       case windows.REG_BINARY:
-               return buf, nil
-       case windows.REG_DWORD_LITTLE_ENDIAN:
-               return binary.LittleEndian.Uint32(buf), nil
-       case windows.REG_DWORD_BIG_ENDIAN:
-               return binary.BigEndian.Uint32(buf), nil
-       case windows.REG_MULTI_SZ:
-               bufW := bufToUTF16(buf)
-               a := []string{}
-               for i := 0; i < len(bufW); {
-                       j := i + wcslen(bufW[i:])
-                       if i < j {
-                               a = append(a, windows.UTF16ToString(bufW[i:j]))
-                       }
-                       i = j + 1
-               }
-               runtime.KeepAlive(buf)
-               return a, nil
-       case windows.REG_QWORD_LITTLE_ENDIAN:
-               return binary.LittleEndian.Uint64(buf), nil
-       default:
-               return nil, fmt.Errorf("Unsupported registry value type: %v", dataType)
-       }
-}
-
-// bufToUTF16 function reinterprets []byte buffer as []uint16
-func bufToUTF16(buf []byte) []uint16 {
-       sl := struct {
-               addr *uint16
-               len  int
-               cap  int
-       }{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2}
-       return *(*[]uint16)(unsafe.Pointer(&sl))
-}
-
-// utf16ToBuf function reinterprets []uint16 as []byte
-func utf16ToBuf(buf []uint16) []byte {
-       sl := struct {
-               addr *byte
-               len  int
-               cap  int
-       }{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2}
-       return *(*[]byte)(unsafe.Pointer(&sl))
-}
-
-func wcslen(str []uint16) int {
-       for i := 0; i < len(str); i++ {
-               if str[i] == 0 {
-                       return i
-               }
-       }
-       return len(str)
-}
-
-// DeviceRegistryProperty method retrieves a specified Plug and Play device property.
-func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) {
-       return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property)
-}
-
-//sys  setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW
-
-// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device.
-func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
-       return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers)))
-}
-
-// SetDeviceRegistryProperty function sets a Plug and Play device property for a device.
-func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error {
-       return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)
-}
-
-// SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device.
-func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {
-       str16, err := windows.UTF16FromString(str)
-       if err != nil {
-               return err
-       }
-       err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
-       runtime.KeepAlive(str16)
-       return err
-}
-
-//sys  setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
-
-// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
-func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) {
-       params := &DevInstallParams{}
-       params.size = uint32(unsafe.Sizeof(*params))
-
-       return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params)
-}
-
-// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element.
-func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) {
-       return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData)
-}
-
-//sys  setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW
-
-// SetupDiGetDeviceInstanceId function retrieves the instance ID of the device.
-func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) {
-       reqSize := uint32(1024)
-       for {
-               buf := make([]uint16, reqSize)
-               err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize)
-               if err == windows.ERROR_INSUFFICIENT_BUFFER {
-                       continue
-               }
-               if err != nil {
-                       return "", err
-               }
-               return windows.UTF16ToString(buf), nil
-       }
-}
-
-// DeviceInstanceID method retrieves the instance ID of the device.
-func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) {
-       return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData)
-}
-
-// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element.
-//sys  SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW
-
-// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element.
-func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error {
-       return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize)
-}
-
-//sys  SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW
-
-// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element.
-func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error {
-       return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams)
-}
-
-// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element.
-//sys  SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW
-
-// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element.
-func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error {
-       return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize)
-}
-
-//sys  setupDiClassNameFromGuidEx(classGUID *windows.GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW
-
-// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer.
-func SetupDiClassNameFromGuidEx(classGUID *windows.GUID, machineName string) (className string, err error) {
-       var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16
-
-       var machineNameUTF16 *uint16
-       if machineName != "" {
-               machineNameUTF16, err = windows.UTF16PtrFromString(machineName)
-               if err != nil {
-                       return
-               }
-       }
-
-       err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0)
-       if err != nil {
-               return
-       }
-
-       className = windows.UTF16ToString(classNameUTF16[:])
-       return
-}
-
-//sys  setupDiClassGuidsFromNameEx(className *uint16, classGuidList *windows.GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW
-
-// SetupDiClassGuidsFromNameEx function retrieves the GUIDs associated with the specified class name. This resulting list contains the classes currently installed on a local or remote computer.
-func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]windows.GUID, error) {
-       classNameUTF16, err := windows.UTF16PtrFromString(className)
-       if err != nil {
-               return nil, err
-       }
-
-       var machineNameUTF16 *uint16
-       if machineName != "" {
-               machineNameUTF16, err = windows.UTF16PtrFromString(machineName)
-               if err != nil {
-                       return nil, err
-               }
-       }
-
-       reqSize := uint32(4)
-       for {
-               buf := make([]windows.GUID, reqSize)
-               err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0)
-               if err == windows.ERROR_INSUFFICIENT_BUFFER {
-                       continue
-               }
-               if err != nil {
-                       return nil, err
-               }
-               return buf[:reqSize], nil
-       }
-}
-
-//sys  setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice
-
-// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set.
-func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) {
-       data := &DevInfoData{}
-       data.size = uint32(unsafe.Sizeof(*data))
-
-       return data, setupDiGetSelectedDevice(deviceInfoSet, data)
-}
-
-// SelectedDevice method retrieves the selected device information element in a device information set.
-func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) {
-       return SetupDiGetSelectedDevice(deviceInfoSet)
-}
-
-// 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 *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice
-
-// SetSelectedDevice method sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard.
-func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error {
-       return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData)
-}
-
-//sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *windows.GUID, deviceID *uint16, flags uint32) (ret uint32) = CfgMgr32.CM_Get_Device_Interface_List_SizeW
-//sys cm_Get_Device_Interface_List(interfaceClass *windows.GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret uint32) = CfgMgr32.CM_Get_Device_Interface_ListW
-
-func CM_Get_Device_Interface_List(deviceID string, interfaceClass *windows.GUID, flags uint32) ([]string, error) {
-       deviceID16, err := windows.UTF16PtrFromString(deviceID)
-       if err != nil {
-               return nil, err
-       }
-       var buf []uint16
-       var buflen uint32
-       for {
-               if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS {
-                       return nil, fmt.Errorf("CfgMgr error: 0x%x", ret)
-               }
-               buf = make([]uint16, buflen)
-               if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS {
-                       break
-               } else if ret != CR_BUFFER_SMALL {
-                       return nil, fmt.Errorf("CfgMgr error: 0x%x", ret)
-               }
-       }
-       var interfaces []string
-       for i := 0; i < len(buf); {
-               j := i + wcslen(buf[i:])
-               if i < j {
-                       interfaces = append(interfaces, windows.UTF16ToString(buf[i:j]))
-               }
-               i = j + 1
-       }
-       if interfaces == nil {
-               return nil, fmt.Errorf("no interfaces found")
-       }
-       return interfaces, nil
-}
diff --git a/tun/wintun/setupapi/setupapi_windows_test.go b/tun/wintun/setupapi/setupapi_windows_test.go
deleted file mode 100644 (file)
index b0afbc7..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-import (
-       "runtime"
-       "strings"
-       "testing"
-
-       "golang.org/x/sys/windows"
-)
-
-var deviceClassNetGUID = windows.GUID{Data1: 0x4d36e972, Data2: 0xe325, Data3: 0x11ce, Data4: [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}
-var computerName string
-
-func init() {
-       computerName, _ = windows.ComputerName()
-}
-
-func TestSetupDiCreateDeviceInfoListEx(t *testing.T) {
-       devInfoList, err := SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, "")
-       if err != nil {
-               t.Errorf("Error calling SetupDiCreateDeviceInfoListEx: %s", err.Error())
-       } else {
-               devInfoList.Close()
-       }
-
-       devInfoList, err = SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiCreateDeviceInfoListEx: %s", err.Error())
-       } else {
-               devInfoList.Close()
-       }
-
-       devInfoList, err = SetupDiCreateDeviceInfoListEx(nil, 0, "")
-       if err != nil {
-               t.Errorf("Error calling SetupDiCreateDeviceInfoListEx(nil): %s", err.Error())
-       } else {
-               devInfoList.Close()
-       }
-}
-
-func TestSetupDiGetDeviceInfoListDetail(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()
-
-       data, err := devInfoList.DeviceInfoListDetail()
-       if err != nil {
-               t.Errorf("Error calling SetupDiGetDeviceInfoListDetail: %s", err.Error())
-       } else {
-               if data.ClassGUID != deviceClassNetGUID {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned different class GUID")
-               }
-
-               if data.RemoteMachineHandle != windows.Handle(0) {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned non-NULL remote machine handle")
-               }
-
-               if data.RemoteMachineName() != "" {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned non-NULL remote machine name")
-               }
-       }
-
-       devInfoList, err = SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, DIGCF_PRESENT, DevInfo(0), computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiGetClassDevsEx: %s", err.Error())
-       }
-       defer devInfoList.Close()
-
-       data, err = devInfoList.DeviceInfoListDetail()
-       if err != nil {
-               t.Errorf("Error calling SetupDiGetDeviceInfoListDetail: %s", err.Error())
-       } else {
-               if data.ClassGUID != deviceClassNetGUID {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned different class GUID")
-               }
-
-               if data.RemoteMachineHandle == windows.Handle(0) {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned NULL remote machine handle")
-               }
-
-               if data.RemoteMachineName() != computerName {
-                       t.Error("SetupDiGetDeviceInfoListDetail returned different remote machine name")
-               }
-       }
-
-       data = &DevInfoListDetailData{}
-       data.SetRemoteMachineName("foobar")
-       if data.RemoteMachineName() != "foobar" {
-               t.Error("DevInfoListDetailData.(Get|Set)RemoteMachineName() differ")
-       }
-}
-
-func TestSetupDiCreateDeviceInfo(t *testing.T) {
-       devInfoList, err := SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiCreateDeviceInfoListEx: %s", err.Error())
-       }
-       defer devInfoList.Close()
-
-       deviceClassNetName, err := SetupDiClassNameFromGuidEx(&deviceClassNetGUID, computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiClassNameFromGuidEx: %s", err.Error())
-       }
-
-       devInfoData, err := devInfoList.CreateDeviceInfo(deviceClassNetName, &deviceClassNetGUID, "This is a test device", 0, DICD_GENERATE_ID)
-       if err != nil {
-               // Access denied is expected, as the SetupDiCreateDeviceInfo() require elevation to succeed.
-               if errWin, ok := err.(windows.Errno); !ok || errWin != windows.ERROR_ACCESS_DENIED {
-                       t.Errorf("Error calling SetupDiCreateDeviceInfo: %s", err.Error())
-               }
-       } else if devInfoData.ClassGUID != deviceClassNetGUID {
-               t.Error("SetupDiCreateDeviceInfo returned different class GUID")
-       }
-}
-
-func TestSetupDiEnumDeviceInfo(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 := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               if data.ClassGUID != deviceClassNetGUID {
-                       t.Error("SetupDiEnumDeviceInfo returned different class GUID")
-               }
-
-               _, err = devInfoList.DeviceInstanceID(data)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceInstanceId: %s", err.Error())
-               }
-       }
-}
-
-func TestDevInfo_BuildDriverInfoList(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++ {
-               deviceData, err := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               const driverType SPDIT = SPDIT_COMPATDRIVER
-               err = devInfoList.BuildDriverInfoList(deviceData, driverType)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiBuildDriverInfoList: %s", err.Error())
-               }
-               defer devInfoList.DestroyDriverInfoList(deviceData, driverType)
-
-               var selectedDriverData *DrvInfoData
-               for j := 0; true; j++ {
-                       driverData, err := devInfoList.EnumDriverInfo(deviceData, driverType, j)
-                       if err != nil {
-                               if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                                       break
-                               }
-                               continue
-                       }
-
-                       if driverData.DriverType == 0 {
-                               continue
-                       }
-
-                       if !driverData.IsNewer(windows.Filetime{}, 0) {
-                               t.Error("Driver should have non-zero date and version")
-                       }
-                       if !driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime}, 0) {
-                               t.Error("Driver should have non-zero date and version")
-                       }
-                       if driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime + 1}, 0) {
-                               t.Error("Driver should report newer version on high-date-time")
-                       }
-                       if !driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime, LowDateTime: driverData.DriverDate.LowDateTime}, 0) {
-                               t.Error("Driver should have non-zero version")
-                       }
-                       if driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime, LowDateTime: driverData.DriverDate.LowDateTime + 1}, 0) {
-                               t.Error("Driver should report newer version on low-date-time")
-                       }
-                       if driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime, LowDateTime: driverData.DriverDate.LowDateTime}, driverData.DriverVersion) {
-                               t.Error("Driver should not be newer than itself")
-                       }
-                       if driverData.IsNewer(windows.Filetime{HighDateTime: driverData.DriverDate.HighDateTime, LowDateTime: driverData.DriverDate.LowDateTime}, driverData.DriverVersion+1) {
-                               t.Error("Driver should report newer version on version")
-                       }
-
-                       err = devInfoList.SetSelectedDriver(deviceData, driverData)
-                       if err != nil {
-                               t.Errorf("Error calling SetupDiSetSelectedDriver: %s", err.Error())
-                       } else {
-                               selectedDriverData = driverData
-                       }
-
-                       driverDetailData, err := devInfoList.DriverInfoDetail(deviceData, driverData)
-                       if err != nil {
-                               t.Errorf("Error calling SetupDiGetDriverInfoDetail: %s", err.Error())
-                       }
-
-                       if driverDetailData.IsCompatible("foobar-aab6e3a4-144e-4786-88d3-6cec361e1edd") {
-                               t.Error("Invalid HWID compatibitlity reported")
-                       }
-                       if !driverDetailData.IsCompatible(strings.ToUpper(driverDetailData.HardwareID())) {
-                               t.Error("HWID compatibitlity missed")
-                       }
-                       a := driverDetailData.CompatIDs()
-                       for k := range a {
-                               if !driverDetailData.IsCompatible(strings.ToUpper(a[k])) {
-                                       t.Error("HWID compatibitlity missed")
-                               }
-                       }
-               }
-
-               selectedDriverData2, err := devInfoList.SelectedDriver(deviceData)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetSelectedDriver: %s", err.Error())
-               } else if *selectedDriverData != *selectedDriverData2 {
-                       t.Error("SetupDiGetSelectedDriver should return driver selected with SetupDiSetSelectedDriver")
-               }
-       }
-
-       data := &DrvInfoData{}
-       data.SetDescription("foobar")
-       if data.Description() != "foobar" {
-               t.Error("DrvInfoData.(Get|Set)Description() differ")
-       }
-       data.SetMfgName("foobar")
-       if data.MfgName() != "foobar" {
-               t.Error("DrvInfoData.(Get|Set)MfgName() differ")
-       }
-       data.SetProviderName("foobar")
-       if data.ProviderName() != "foobar" {
-               t.Error("DrvInfoData.(Get|Set)ProviderName() differ")
-       }
-}
-
-func TestSetupDiGetClassDevsEx(t *testing.T) {
-       devInfoList, err := SetupDiGetClassDevsEx(&deviceClassNetGUID, "PCI", 0, DIGCF_PRESENT, DevInfo(0), computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiGetClassDevsEx: %s", err.Error())
-       } else {
-               devInfoList.Close()
-       }
-
-       devInfoList, err = SetupDiGetClassDevsEx(nil, "", 0, DIGCF_PRESENT, DevInfo(0), "")
-       if err != nil {
-               if errWin, ok := err.(windows.Errno); !ok || errWin != windows.ERROR_INVALID_PARAMETER {
-                       t.Errorf("SetupDiGetClassDevsEx(nil, ...) should fail with ERROR_INVALID_PARAMETER")
-               }
-       } else {
-               devInfoList.Close()
-               t.Errorf("SetupDiGetClassDevsEx(nil, ...) should fail")
-       }
-}
-
-func TestSetupDiOpenDevRegKey(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 := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               key, err := devInfoList.OpenDevRegKey(data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, windows.KEY_READ)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiOpenDevRegKey: %s", err.Error())
-               }
-               defer key.Close()
-       }
-}
-
-func TestSetupDiGetDeviceRegistryProperty(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 := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               val, err := devInfoList.DeviceRegistryProperty(data, SPDRP_CLASS)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceRegistryProperty(SPDRP_CLASS): %s", err.Error())
-               } else if class, ok := val.(string); !ok || strings.ToLower(class) != "net" {
-                       t.Errorf("SetupDiGetDeviceRegistryProperty(SPDRP_CLASS) should return \"Net\"")
-               }
-
-               val, err = devInfoList.DeviceRegistryProperty(data, SPDRP_CLASSGUID)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceRegistryProperty(SPDRP_CLASSGUID): %s", err.Error())
-               } else if valStr, ok := val.(string); !ok {
-                       t.Errorf("SetupDiGetDeviceRegistryProperty(SPDRP_CLASSGUID) should return string")
-               } else {
-                       classGUID, err := windows.GUIDFromString(valStr)
-                       if err != nil {
-                               t.Errorf("Error parsing GUID returned by SetupDiGetDeviceRegistryProperty(SPDRP_CLASSGUID): %s", err.Error())
-                       } else if classGUID != deviceClassNetGUID {
-                               t.Errorf("SetupDiGetDeviceRegistryProperty(SPDRP_CLASSGUID) should return %x", deviceClassNetGUID)
-                       }
-               }
-
-               val, err = devInfoList.DeviceRegistryProperty(data, SPDRP_COMPATIBLEIDS)
-               if err != nil {
-                       // Some devices have no SPDRP_COMPATIBLEIDS.
-                       if errWin, ok := err.(windows.Errno); !ok || errWin != windows.ERROR_INVALID_DATA {
-                               t.Errorf("Error calling SetupDiGetDeviceRegistryProperty(SPDRP_COMPATIBLEIDS): %s", err.Error())
-                       }
-               }
-
-               val, err = devInfoList.DeviceRegistryProperty(data, SPDRP_CONFIGFLAGS)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceRegistryProperty(SPDRP_CONFIGFLAGS): %s", err.Error())
-               }
-
-               val, err = devInfoList.DeviceRegistryProperty(data, SPDRP_DEVICE_POWER_DATA)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceRegistryProperty(SPDRP_DEVICE_POWER_DATA): %s", err.Error())
-               }
-       }
-}
-
-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()
-
-       for i := 0; true; i++ {
-               data, err := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               _, err = devInfoList.DeviceInstallParams(data)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiGetDeviceInstallParams: %s", err.Error())
-               }
-       }
-
-       params := &DevInstallParams{}
-       params.SetDriverPath("foobar")
-       if params.DriverPath() != "foobar" {
-               t.Error("DevInstallParams.(Get|Set)DriverPath() differ")
-       }
-}
-
-func TestSetupDiClassNameFromGuidEx(t *testing.T) {
-       deviceClassNetName, err := SetupDiClassNameFromGuidEx(&deviceClassNetGUID, "")
-       if err != nil {
-               t.Errorf("Error calling SetupDiClassNameFromGuidEx: %s", err.Error())
-       } else if strings.ToLower(deviceClassNetName) != "net" {
-               t.Errorf("SetupDiClassNameFromGuidEx(%x) should return \"Net\"", deviceClassNetGUID)
-       }
-
-       deviceClassNetName, err = SetupDiClassNameFromGuidEx(&deviceClassNetGUID, computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiClassNameFromGuidEx: %s", err.Error())
-       } else if strings.ToLower(deviceClassNetName) != "net" {
-               t.Errorf("SetupDiClassNameFromGuidEx(%x) should return \"Net\"", deviceClassNetGUID)
-       }
-
-       _, err = SetupDiClassNameFromGuidEx(nil, "")
-       if err != nil {
-               if errWin, ok := err.(windows.Errno); !ok || errWin != windows.ERROR_INVALID_USER_BUFFER {
-                       t.Errorf("SetupDiClassNameFromGuidEx(nil) should fail with ERROR_INVALID_USER_BUFFER")
-               }
-       } else {
-               t.Errorf("SetupDiClassNameFromGuidEx(nil) should fail")
-       }
-}
-
-func TestSetupDiClassGuidsFromNameEx(t *testing.T) {
-       ClassGUIDs, err := SetupDiClassGuidsFromNameEx("Net", "")
-       if err != nil {
-               t.Errorf("Error calling SetupDiClassGuidsFromNameEx: %s", err.Error())
-       } else {
-               found := false
-               for i := range ClassGUIDs {
-                       if ClassGUIDs[i] == deviceClassNetGUID {
-                               found = true
-                               break
-                       }
-               }
-               if !found {
-                       t.Errorf("SetupDiClassGuidsFromNameEx(\"Net\") should return %x", deviceClassNetGUID)
-               }
-       }
-
-       ClassGUIDs, err = SetupDiClassGuidsFromNameEx("foobar-34274a51-a6e6-45f0-80d6-c62be96dd5fe", computerName)
-       if err != nil {
-               t.Errorf("Error calling SetupDiClassGuidsFromNameEx: %s", err.Error())
-       } else if len(ClassGUIDs) != 0 {
-               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 := devInfoList.EnumDeviceInfo(i)
-               if err != nil {
-                       if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               err = devInfoList.SetSelectedDevice(data)
-               if err != nil {
-                       t.Errorf("Error calling SetupDiSetSelectedDevice: %s", err.Error())
-               }
-
-               data2, err := devInfoList.SelectedDevice()
-               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 = devInfoList.SetSelectedDevice(nil)
-       if err != nil {
-               if errWin, ok := err.(windows.Errno); !ok || errWin != windows.ERROR_INVALID_PARAMETER {
-                       t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER")
-               }
-       } else {
-               t.Errorf("SetupDiSetSelectedDevice(nil) should fail")
-       }
-}
-
-func TestUTF16ToBuf(t *testing.T) {
-       buf := []uint16{0x0123, 0x4567, 0x89ab, 0xcdef}
-       buf2 := utf16ToBuf(buf)
-       if len(buf)*2 != len(buf2) ||
-               cap(buf)*2 != cap(buf2) ||
-               buf2[0] != 0x23 || buf2[1] != 0x01 ||
-               buf2[2] != 0x67 || buf2[3] != 0x45 ||
-               buf2[4] != 0xab || buf2[5] != 0x89 ||
-               buf2[6] != 0xef || buf2[7] != 0xcd {
-               t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER")
-       }
-       runtime.KeepAlive(buf)
-}
diff --git a/tun/wintun/setupapi/types32_windows.go b/tun/wintun/setupapi/types32_windows.go
deleted file mode 100644 (file)
index 0eaead6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build 386 arm
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-const (
-       sizeofDevInfoListDetailData uint32 = 550
-       sizeofDrvInfoDetailData     uint32 = 1570
-)
diff --git a/tun/wintun/setupapi/types64_windows.go b/tun/wintun/setupapi/types64_windows.go
deleted file mode 100644 (file)
index c815b8f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build amd64 arm64
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-const (
-       sizeofDevInfoListDetailData uint32 = 560
-       sizeofDrvInfoDetailData     uint32 = 1584
-)
diff --git a/tun/wintun/setupapi/types_windows.go b/tun/wintun/setupapi/types_windows.go
deleted file mode 100644 (file)
index 43e3f39..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-import (
-       "strings"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-const (
-       MAX_DEVICE_ID_LEN   = 200
-       MAX_DEVNODE_ID_LEN  = MAX_DEVICE_ID_LEN
-       MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null
-       MAX_CLASS_NAME_LEN  = 32
-       MAX_PROFILE_LEN     = 80
-       MAX_CONFIG_VALUE    = 9999
-       MAX_INSTANCE_VALUE  = 9999
-       CONFIGMG_VERSION    = 0x0400
-)
-
-//
-// Define maximum string length constants
-//
-const (
-       ANYSIZE_ARRAY               = 1
-       LINE_LEN                    = 256  // Windows 9x-compatible maximum for displayable strings coming from a device INF.
-       MAX_INF_STRING_LENGTH       = 4096 // Actual maximum size of an INF string (including string substitutions).
-       MAX_INF_SECTION_NAME_LENGTH = 255  // For Windows 9x compatibility, INF section names should be constrained to 32 characters.
-       MAX_TITLE_LEN               = 60
-       MAX_INSTRUCTION_LEN         = 256
-       MAX_LABEL_LEN               = 30
-       MAX_SERVICE_NAME_LEN        = 256
-       MAX_SUBTITLE_LEN            = 256
-)
-
-const (
-       // SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0").
-       SP_MAX_MACHINENAME_LENGTH = windows.MAX_PATH + 3
-)
-
-// HSPFILEQ is type for setup file queue
-type HSPFILEQ uintptr
-
-// DevInfo holds reference to device information set
-type DevInfo windows.Handle
-
-// DevInfoData is a device information structure (references a device instance that is a member of a device information set)
-type DevInfoData struct {
-       size      uint32
-       ClassGUID windows.GUID
-       DevInst   uint32 // DEVINST handle
-       _         uintptr
-}
-
-// DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass).
-type DevInfoListDetailData struct {
-       size                uint32 // Warning: unsafe.Sizeof(DevInfoListDetailData) > sizeof(SP_DEVINFO_LIST_DETAIL_DATA) when GOARCH == 386 => use sizeofDevInfoListDetailData const.
-       ClassGUID           windows.GUID
-       RemoteMachineHandle windows.Handle
-       remoteMachineName   [SP_MAX_MACHINENAME_LENGTH]uint16
-}
-
-func (data *DevInfoListDetailData) RemoteMachineName() string {
-       return windows.UTF16ToString(data.remoteMachineName[:])
-}
-
-func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error {
-       str, err := windows.UTF16FromString(remoteMachineName)
-       if err != nil {
-               return err
-       }
-       copy(data.remoteMachineName[:], str)
-       return nil
-}
-
-// DI_FUNCTION is function type for device installer
-type DI_FUNCTION uint32
-
-const (
-       DIF_SELECTDEVICE                   DI_FUNCTION = 0x00000001
-       DIF_INSTALLDEVICE                  DI_FUNCTION = 0x00000002
-       DIF_ASSIGNRESOURCES                DI_FUNCTION = 0x00000003
-       DIF_PROPERTIES                     DI_FUNCTION = 0x00000004
-       DIF_REMOVE                         DI_FUNCTION = 0x00000005
-       DIF_FIRSTTIMESETUP                 DI_FUNCTION = 0x00000006
-       DIF_FOUNDDEVICE                    DI_FUNCTION = 0x00000007
-       DIF_SELECTCLASSDRIVERS             DI_FUNCTION = 0x00000008
-       DIF_VALIDATECLASSDRIVERS           DI_FUNCTION = 0x00000009
-       DIF_INSTALLCLASSDRIVERS            DI_FUNCTION = 0x0000000A
-       DIF_CALCDISKSPACE                  DI_FUNCTION = 0x0000000B
-       DIF_DESTROYPRIVATEDATA             DI_FUNCTION = 0x0000000C
-       DIF_VALIDATEDRIVER                 DI_FUNCTION = 0x0000000D
-       DIF_DETECT                         DI_FUNCTION = 0x0000000F
-       DIF_INSTALLWIZARD                  DI_FUNCTION = 0x00000010
-       DIF_DESTROYWIZARDDATA              DI_FUNCTION = 0x00000011
-       DIF_PROPERTYCHANGE                 DI_FUNCTION = 0x00000012
-       DIF_ENABLECLASS                    DI_FUNCTION = 0x00000013
-       DIF_DETECTVERIFY                   DI_FUNCTION = 0x00000014
-       DIF_INSTALLDEVICEFILES             DI_FUNCTION = 0x00000015
-       DIF_UNREMOVE                       DI_FUNCTION = 0x00000016
-       DIF_SELECTBESTCOMPATDRV            DI_FUNCTION = 0x00000017
-       DIF_ALLOW_INSTALL                  DI_FUNCTION = 0x00000018
-       DIF_REGISTERDEVICE                 DI_FUNCTION = 0x00000019
-       DIF_NEWDEVICEWIZARD_PRESELECT      DI_FUNCTION = 0x0000001A
-       DIF_NEWDEVICEWIZARD_SELECT         DI_FUNCTION = 0x0000001B
-       DIF_NEWDEVICEWIZARD_PREANALYZE     DI_FUNCTION = 0x0000001C
-       DIF_NEWDEVICEWIZARD_POSTANALYZE    DI_FUNCTION = 0x0000001D
-       DIF_NEWDEVICEWIZARD_FINISHINSTALL  DI_FUNCTION = 0x0000001E
-       DIF_INSTALLINTERFACES              DI_FUNCTION = 0x00000020
-       DIF_DETECTCANCEL                   DI_FUNCTION = 0x00000021
-       DIF_REGISTER_COINSTALLERS          DI_FUNCTION = 0x00000022
-       DIF_ADDPROPERTYPAGE_ADVANCED       DI_FUNCTION = 0x00000023
-       DIF_ADDPROPERTYPAGE_BASIC          DI_FUNCTION = 0x00000024
-       DIF_TROUBLESHOOTER                 DI_FUNCTION = 0x00000026
-       DIF_POWERMESSAGEWAKE               DI_FUNCTION = 0x00000027
-       DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028
-       DIF_UPDATEDRIVER_UI                DI_FUNCTION = 0x00000029
-       DIF_FINISHINSTALL_ACTION           DI_FUNCTION = 0x0000002A
-)
-
-// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set)
-type DevInstallParams struct {
-       size                     uint32
-       Flags                    DI_FLAGS
-       FlagsEx                  DI_FLAGSEX
-       hwndParent               uintptr
-       InstallMsgHandler        uintptr
-       InstallMsgHandlerContext uintptr
-       FileQueue                HSPFILEQ
-       _                        uintptr
-       _                        uint32
-       driverPath               [windows.MAX_PATH]uint16
-}
-
-func (params *DevInstallParams) DriverPath() string {
-       return windows.UTF16ToString(params.driverPath[:])
-}
-
-func (params *DevInstallParams) SetDriverPath(driverPath string) error {
-       str, err := windows.UTF16FromString(driverPath)
-       if err != nil {
-               return err
-       }
-       copy(params.driverPath[:], str)
-       return nil
-}
-
-// 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
-)
-
-// ClassInstallHeader is the first member of any class install parameters structure. It contains the device installation request code that defines the format of the rest of the install parameters structure.
-type ClassInstallHeader struct {
-       size            uint32
-       InstallFunction DI_FUNCTION
-}
-
-func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader {
-       hdr := &ClassInstallHeader{InstallFunction: installFunction}
-       hdr.size = uint32(unsafe.Sizeof(*hdr))
-       return hdr
-}
-
-// DICS_STATE specifies values indicating a change in a device's state
-type DICS_STATE uint32
-
-const (
-       DICS_ENABLE     DICS_STATE = 0x00000001 // The device is being enabled.
-       DICS_DISABLE    DICS_STATE = 0x00000002 // The device is being disabled.
-       DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed.
-       DICS_START      DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile).
-       DICS_STOP       DICS_STATE = 0x00000005 // The device is being stopped. The driver stack will be unloaded and the CSCONFIGFLAG_DO_NOT_START flag will be set for the device.
-)
-
-// DICS_FLAG specifies the scope of a device property change
-type DICS_FLAG uint32
-
-const (
-       DICS_FLAG_GLOBAL         DICS_FLAG = 0x00000001 // make change in all hardware profiles
-       DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only
-       DICS_FLAG_CONFIGGENERAL  DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete)
-)
-
-// PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function.
-type PropChangeParams struct {
-       ClassInstallHeader ClassInstallHeader
-       StateChange        DICS_STATE
-       Scope              DICS_FLAG
-       HwProfile          uint32
-}
-
-// DI_REMOVEDEVICE specifies the scope of the device removal
-type DI_REMOVEDEVICE uint32
-
-const (
-       DI_REMOVEDEVICE_GLOBAL         DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry.
-       DI_REMOVEDEVICE_CONFIGSPECIFIC DI_REMOVEDEVICE = 0x00000002 // Make this change to only the hardware profile specified by HwProfile. this flag only applies to root-enumerated devices. When Windows removes the device from the last hardware profile in which it was configured, Windows performs a global removal.
-)
-
-// RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function.
-type RemoveDeviceParams struct {
-       ClassInstallHeader ClassInstallHeader
-       Scope              DI_REMOVEDEVICE
-       HwProfile          uint32
-}
-
-// DrvInfoData is driver information structure (member of a driver info list that may be associated with a particular device instance, or (globally) with a device information set)
-type DrvInfoData struct {
-       size          uint32
-       DriverType    uint32
-       _             uintptr
-       description   [LINE_LEN]uint16
-       mfgName       [LINE_LEN]uint16
-       providerName  [LINE_LEN]uint16
-       DriverDate    windows.Filetime
-       DriverVersion uint64
-}
-
-func (data *DrvInfoData) Description() string {
-       return windows.UTF16ToString(data.description[:])
-}
-
-func (data *DrvInfoData) SetDescription(description string) error {
-       str, err := windows.UTF16FromString(description)
-       if err != nil {
-               return err
-       }
-       copy(data.description[:], str)
-       return nil
-}
-
-func (data *DrvInfoData) MfgName() string {
-       return windows.UTF16ToString(data.mfgName[:])
-}
-
-func (data *DrvInfoData) SetMfgName(mfgName string) error {
-       str, err := windows.UTF16FromString(mfgName)
-       if err != nil {
-               return err
-       }
-       copy(data.mfgName[:], str)
-       return nil
-}
-
-func (data *DrvInfoData) ProviderName() string {
-       return windows.UTF16ToString(data.providerName[:])
-}
-
-func (data *DrvInfoData) SetProviderName(providerName string) error {
-       str, err := windows.UTF16FromString(providerName)
-       if err != nil {
-               return err
-       }
-       copy(data.providerName[:], str)
-       return nil
-}
-
-// IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters.
-func (data *DrvInfoData) IsNewer(driverDate windows.Filetime, driverVersion uint64) bool {
-       if data.DriverDate.HighDateTime > driverDate.HighDateTime {
-               return true
-       }
-       if data.DriverDate.HighDateTime < driverDate.HighDateTime {
-               return false
-       }
-
-       if data.DriverDate.LowDateTime > driverDate.LowDateTime {
-               return true
-       }
-       if data.DriverDate.LowDateTime < driverDate.LowDateTime {
-               return false
-       }
-
-       if data.DriverVersion > driverVersion {
-               return true
-       }
-       if data.DriverVersion < driverVersion {
-               return false
-       }
-
-       return false
-}
-
-// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure)
-type DrvInfoDetailData struct {
-       size            uint32 // Warning: unsafe.Sizeof(DrvInfoDetailData) > sizeof(SP_DRVINFO_DETAIL_DATA) when GOARCH == 386 => use sizeofDrvInfoDetailData const.
-       InfDate         windows.Filetime
-       compatIDsOffset uint32
-       compatIDsLength uint32
-       _               uintptr
-       sectionName     [LINE_LEN]uint16
-       infFileName     [windows.MAX_PATH]uint16
-       drvDescription  [LINE_LEN]uint16
-       hardwareID      [ANYSIZE_ARRAY]uint16
-}
-
-func (data *DrvInfoDetailData) SectionName() string {
-       return windows.UTF16ToString(data.sectionName[:])
-}
-
-func (data *DrvInfoDetailData) InfFileName() string {
-       return windows.UTF16ToString(data.infFileName[:])
-}
-
-func (data *DrvInfoDetailData) DrvDescription() string {
-       return windows.UTF16ToString(data.drvDescription[:])
-}
-
-func (data *DrvInfoDetailData) HardwareID() string {
-       if data.compatIDsOffset > 1 {
-               bufW := data.getBuf()
-               return windows.UTF16ToString(bufW[:wcslen(bufW)])
-       }
-
-       return ""
-}
-
-func (data *DrvInfoDetailData) CompatIDs() []string {
-       a := make([]string, 0)
-
-       if data.compatIDsLength > 0 {
-               bufW := data.getBuf()
-               bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength]
-               for i := 0; i < len(bufW); {
-                       j := i + wcslen(bufW[i:])
-                       if i < j {
-                               a = append(a, windows.UTF16ToString(bufW[i:j]))
-                       }
-                       i = j + 1
-               }
-       }
-
-       return a
-}
-
-func (data *DrvInfoDetailData) getBuf() []uint16 {
-       len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2
-       sl := struct {
-               addr *uint16
-               len  int
-               cap  int
-       }{&data.hardwareID[0], int(len), int(len)}
-       return *(*[]uint16)(unsafe.Pointer(&sl))
-}
-
-// IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list.
-func (data *DrvInfoDetailData) IsCompatible(hwid string) bool {
-       hwidLC := strings.ToLower(hwid)
-       if strings.ToLower(data.HardwareID()) == hwidLC {
-               return true
-       }
-       a := data.CompatIDs()
-       for i := range a {
-               if strings.ToLower(a[i]) == hwidLC {
-                       return true
-               }
-       }
-
-       return false
-}
-
-// DICD flags control SetupDiCreateDeviceInfo
-type DICD uint32
-
-const (
-       DICD_GENERATE_ID       DICD = 0x00000001
-       DICD_INHERIT_CLASSDRVS DICD = 0x00000002
-)
-
-//
-// SPDIT flags to distinguish between class drivers and
-// device drivers.
-// (Passed in 'DriverType' parameter of driver information list APIs)
-//
-type SPDIT uint32
-
-const (
-       SPDIT_NODRIVER     SPDIT = 0x00000000
-       SPDIT_CLASSDRIVER  SPDIT = 0x00000001
-       SPDIT_COMPATDRIVER SPDIT = 0x00000002
-)
-
-// DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs
-type DIGCF uint32
-
-const (
-       DIGCF_DEFAULT         DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE
-       DIGCF_PRESENT         DIGCF = 0x00000002
-       DIGCF_ALLCLASSES      DIGCF = 0x00000004
-       DIGCF_PROFILE         DIGCF = 0x00000008
-       DIGCF_DEVICEINTERFACE DIGCF = 0x00000010
-)
-
-// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey.
-type DIREG uint32
-
-const (
-       DIREG_DEV  DIREG = 0x00000001 // Open/Create/Delete device key
-       DIREG_DRV  DIREG = 0x00000002 // Open/Create/Delete driver key
-       DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key
-)
-
-//
-// SPDRP specifies device registry property codes
-// (Codes marked as read-only (R) may only be used for
-// SetupDiGetDeviceRegistryProperty)
-//
-// These values should cover the same set of registry properties
-// as defined by the CM_DRP codes in cfgmgr32.h.
-//
-// Note that SPDRP codes are zero based while CM_DRP codes are one based!
-//
-type SPDRP uint32
-
-const (
-       SPDRP_DEVICEDESC                  SPDRP = 0x00000000 // DeviceDesc (R/W)
-       SPDRP_HARDWAREID                  SPDRP = 0x00000001 // HardwareID (R/W)
-       SPDRP_COMPATIBLEIDS               SPDRP = 0x00000002 // CompatibleIDs (R/W)
-       SPDRP_SERVICE                     SPDRP = 0x00000004 // Service (R/W)
-       SPDRP_CLASS                       SPDRP = 0x00000007 // Class (R--tied to ClassGUID)
-       SPDRP_CLASSGUID                   SPDRP = 0x00000008 // ClassGUID (R/W)
-       SPDRP_DRIVER                      SPDRP = 0x00000009 // Driver (R/W)
-       SPDRP_CONFIGFLAGS                 SPDRP = 0x0000000A // ConfigFlags (R/W)
-       SPDRP_MFG                         SPDRP = 0x0000000B // Mfg (R/W)
-       SPDRP_FRIENDLYNAME                SPDRP = 0x0000000C // FriendlyName (R/W)
-       SPDRP_LOCATION_INFORMATION        SPDRP = 0x0000000D // LocationInformation (R/W)
-       SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R)
-       SPDRP_CAPABILITIES                SPDRP = 0x0000000F // Capabilities (R)
-       SPDRP_UI_NUMBER                   SPDRP = 0x00000010 // UiNumber (R)
-       SPDRP_UPPERFILTERS                SPDRP = 0x00000011 // UpperFilters (R/W)
-       SPDRP_LOWERFILTERS                SPDRP = 0x00000012 // LowerFilters (R/W)
-       SPDRP_BUSTYPEGUID                 SPDRP = 0x00000013 // BusTypeGUID (R)
-       SPDRP_LEGACYBUSTYPE               SPDRP = 0x00000014 // LegacyBusType (R)
-       SPDRP_BUSNUMBER                   SPDRP = 0x00000015 // BusNumber (R)
-       SPDRP_ENUMERATOR_NAME             SPDRP = 0x00000016 // Enumerator Name (R)
-       SPDRP_SECURITY                    SPDRP = 0x00000017 // Security (R/W, binary form)
-       SPDRP_SECURITY_SDS                SPDRP = 0x00000018 // Security (W, SDS form)
-       SPDRP_DEVTYPE                     SPDRP = 0x00000019 // Device Type (R/W)
-       SPDRP_EXCLUSIVE                   SPDRP = 0x0000001A // Device is exclusive-access (R/W)
-       SPDRP_CHARACTERISTICS             SPDRP = 0x0000001B // Device Characteristics (R/W)
-       SPDRP_ADDRESS                     SPDRP = 0x0000001C // Device Address (R)
-       SPDRP_UI_NUMBER_DESC_FORMAT       SPDRP = 0x0000001D // UiNumberDescFormat (R/W)
-       SPDRP_DEVICE_POWER_DATA           SPDRP = 0x0000001E // Device Power Data (R)
-       SPDRP_REMOVAL_POLICY              SPDRP = 0x0000001F // Removal Policy (R)
-       SPDRP_REMOVAL_POLICY_HW_DEFAULT   SPDRP = 0x00000020 // Hardware Removal Policy (R)
-       SPDRP_REMOVAL_POLICY_OVERRIDE     SPDRP = 0x00000021 // Removal Policy Override (RW)
-       SPDRP_INSTALL_STATE               SPDRP = 0x00000022 // Device Install State (R)
-       SPDRP_LOCATION_PATHS              SPDRP = 0x00000023 // Device Location Paths (R)
-       SPDRP_BASE_CONTAINERID            SPDRP = 0x00000024 // Base ContainerID (R)
-
-       SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals
-)
-
-const (
-       CR_SUCCESS      = 0x0
-       CR_BUFFER_SMALL = 0x1a
-)
-
-const (
-       CM_GET_DEVICE_INTERFACE_LIST_PRESENT     = 0 // only currently 'live' device interfaces
-       CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not
-)
diff --git a/tun/wintun/setupapi/zsetupapi_windows.go b/tun/wintun/setupapi/zsetupapi_windows.go
deleted file mode 100644 (file)
index 375862d..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package setupapi
-
-import (
-       "syscall"
-       "unsafe"
-
-       "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
-       errnoERROR_IO_PENDING = 997
-)
-
-var (
-       errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-       switch e {
-       case 0:
-               return nil
-       case errnoERROR_IO_PENDING:
-               return errERROR_IO_PENDING
-       }
-       // TODO: add more here, after collecting data on the common
-       // error values see on Windows. (perhaps when running
-       // all.bat?)
-       return e
-}
-
-var (
-       modsetupapi = windows.NewLazySystemDLL("setupapi.dll")
-       modCfgMgr32 = windows.NewLazySystemDLL("CfgMgr32.dll")
-
-       procSetupDiCreateDeviceInfoListExW     = modsetupapi.NewProc("SetupDiCreateDeviceInfoListExW")
-       procSetupDiGetDeviceInfoListDetailW    = modsetupapi.NewProc("SetupDiGetDeviceInfoListDetailW")
-       procSetupDiCreateDeviceInfoW           = modsetupapi.NewProc("SetupDiCreateDeviceInfoW")
-       procSetupDiEnumDeviceInfo              = modsetupapi.NewProc("SetupDiEnumDeviceInfo")
-       procSetupDiDestroyDeviceInfoList       = modsetupapi.NewProc("SetupDiDestroyDeviceInfoList")
-       procSetupDiBuildDriverInfoList         = modsetupapi.NewProc("SetupDiBuildDriverInfoList")
-       procSetupDiCancelDriverInfoSearch      = modsetupapi.NewProc("SetupDiCancelDriverInfoSearch")
-       procSetupDiEnumDriverInfoW             = modsetupapi.NewProc("SetupDiEnumDriverInfoW")
-       procSetupDiGetSelectedDriverW          = modsetupapi.NewProc("SetupDiGetSelectedDriverW")
-       procSetupDiSetSelectedDriverW          = modsetupapi.NewProc("SetupDiSetSelectedDriverW")
-       procSetupDiGetDriverInfoDetailW        = modsetupapi.NewProc("SetupDiGetDriverInfoDetailW")
-       procSetupDiDestroyDriverInfoList       = modsetupapi.NewProc("SetupDiDestroyDriverInfoList")
-       procSetupDiGetClassDevsExW             = modsetupapi.NewProc("SetupDiGetClassDevsExW")
-       procSetupDiCallClassInstaller          = modsetupapi.NewProc("SetupDiCallClassInstaller")
-       procSetupDiOpenDevRegKey               = modsetupapi.NewProc("SetupDiOpenDevRegKey")
-       procSetupDiGetDeviceRegistryPropertyW  = modsetupapi.NewProc("SetupDiGetDeviceRegistryPropertyW")
-       procSetupDiSetDeviceRegistryPropertyW  = modsetupapi.NewProc("SetupDiSetDeviceRegistryPropertyW")
-       procSetupDiGetDeviceInstallParamsW     = modsetupapi.NewProc("SetupDiGetDeviceInstallParamsW")
-       procSetupDiGetDeviceInstanceIdW        = modsetupapi.NewProc("SetupDiGetDeviceInstanceIdW")
-       procSetupDiGetClassInstallParamsW      = modsetupapi.NewProc("SetupDiGetClassInstallParamsW")
-       procSetupDiSetDeviceInstallParamsW     = modsetupapi.NewProc("SetupDiSetDeviceInstallParamsW")
-       procSetupDiSetClassInstallParamsW      = modsetupapi.NewProc("SetupDiSetClassInstallParamsW")
-       procSetupDiClassNameFromGuidExW        = modsetupapi.NewProc("SetupDiClassNameFromGuidExW")
-       procSetupDiClassGuidsFromNameExW       = modsetupapi.NewProc("SetupDiClassGuidsFromNameExW")
-       procSetupDiGetSelectedDevice           = modsetupapi.NewProc("SetupDiGetSelectedDevice")
-       procSetupDiSetSelectedDevice           = modsetupapi.NewProc("SetupDiSetSelectedDevice")
-       procCM_Get_Device_Interface_List_SizeW = modCfgMgr32.NewProc("CM_Get_Device_Interface_List_SizeW")
-       procCM_Get_Device_Interface_ListW      = modCfgMgr32.NewProc("CM_Get_Device_Interface_ListW")
-)
-
-func setupDiCreateDeviceInfoListEx(classGUID *windows.GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) {
-       r0, _, e1 := syscall.Syscall6(procSetupDiCreateDeviceInfoListExW.Addr(), 4, uintptr(unsafe.Pointer(classGUID)), uintptr(hwndParent), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0)
-       handle = DevInfo(r0)
-       if handle == DevInfo(windows.InvalidHandle) {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInfoListDetailW.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoSetDetailData)), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *windows.GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall9(procSetupDiCreateDeviceInfoW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(DeviceName)), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(DeviceDescription)), uintptr(hwndParent), uintptr(CreationFlags), uintptr(unsafe.Pointer(deviceInfoData)), 0, 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiEnumDeviceInfo.Addr(), 3, uintptr(deviceInfoSet), uintptr(memberIndex), uintptr(unsafe.Pointer(deviceInfoData)))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiDestroyDeviceInfoList.Addr(), 1, uintptr(deviceInfoSet), 0, 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiBuildDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiCancelDriverInfoSearch.Addr(), 1, uintptr(deviceInfoSet), 0, 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiEnumDriverInfoW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType), uintptr(memberIndex), uintptr(unsafe.Pointer(driverInfoData)), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiGetDriverInfoDetailW.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)), uintptr(unsafe.Pointer(driverInfoDetailData)), uintptr(driverInfoDetailDataSize), uintptr(unsafe.Pointer(requiredSize)))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiDestroyDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetClassDevsEx(classGUID *windows.GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) {
-       r0, _, e1 := syscall.Syscall9(procSetupDiGetClassDevsExW.Addr(), 7, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(Enumerator)), uintptr(hwndParent), uintptr(Flags), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0)
-       handle = DevInfo(r0)
-       if handle == DevInfo(windows.InvalidHandle) {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) {
-       r1, _, e1 := syscall.Syscall(procSetupDiCallClassInstaller.Addr(), 3, uintptr(installFunction), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key windows.Handle, err error) {
-       r0, _, e1 := syscall.Syscall6(procSetupDiOpenDevRegKey.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(Scope), uintptr(HwProfile), uintptr(KeyType), uintptr(samDesired))
-       key = windows.Handle(r0)
-       if key == windows.InvalidHandle {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) {
-       r1, _, e1 := syscall.Syscall9(procSetupDiGetDeviceRegistryPropertyW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyRegDataType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), 0, 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiSetDeviceRegistryPropertyW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (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 setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiGetDeviceInstanceIdW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(instanceId)), uintptr(instanceIdSize), uintptr(unsafe.Pointer(instanceIdRequiredSize)), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiGetClassInstallParamsW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), uintptr(unsafe.Pointer(requiredSize)), 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (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
-}
-
-func SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiSetClassInstallParamsW.Addr(), 4, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), 0, 0)
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiClassNameFromGuidEx(classGUID *windows.GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiClassNameFromGuidExW.Addr(), 6, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(className)), uintptr(classNameSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiClassGuidsFromNameEx(className *uint16, classGuidList *windows.GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) {
-       r1, _, e1 := syscall.Syscall6(procSetupDiClassGuidsFromNameExW.Addr(), 6, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(classGuidList)), uintptr(classGuidListSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved))
-       if r1 == 0 {
-               if e1 != 0 {
-                       err = errnoErr(e1)
-               } else {
-                       err = syscall.EINVAL
-               }
-       }
-       return
-}
-
-func setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (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 *DevInfoData) (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
-}
-
-func cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *windows.GUID, deviceID *uint16, flags uint32) (ret uint32) {
-       r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_List_SizeW.Addr(), 4, uintptr(unsafe.Pointer(len)), uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(flags), 0, 0)
-       ret = uint32(r0)
-       return
-}
-
-func cm_Get_Device_Interface_List(interfaceClass *windows.GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret uint32) {
-       r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_ListW.Addr(), 5, uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(unsafe.Pointer(buffer)), uintptr(bufferLen), uintptr(flags), 0)
-       ret = uint32(r0)
-       return
-}
diff --git a/tun/wintun/setupapi/zsetupapi_windows_test.go b/tun/wintun/setupapi/zsetupapi_windows_test.go
deleted file mode 100644 (file)
index 5b5f369..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2020 WireGuard LLC. All Rights Reserved.
- */
-
-package setupapi
-
-import (
-       "syscall"
-       "testing"
-
-       "golang.org/x/sys/windows"
-)
-
-func TestSetupDiDestroyDeviceInfoList(t *testing.T) {
-       err := SetupDiDestroyDeviceInfoList(DevInfo(windows.InvalidHandle))
-       if errWin, ok := err.(syscall.Errno); !ok || errWin != windows.ERROR_INVALID_HANDLE {
-               t.Errorf("SetupDiDestroyDeviceInfoList(nil, ...) should fail with ERROR_INVALID_HANDLE")
-       }
-}
index eed4f017679d6878f64496ec2f7fbdc4b2c49d41..14b0260cadc93d29615fb9e99eb1e368ddb17b93 100644 (file)
@@ -7,814 +7,221 @@ package wintun
 
 import (
        "errors"
-       "fmt"
-       "strings"
-       "time"
+       "log"
+       "runtime"
+       "syscall"
        "unsafe"
 
        "golang.org/x/sys/windows"
-       "golang.org/x/sys/windows/registry"
-
-       "golang.zx2c4.com/wireguard/tun/wintun/iphlpapi"
-       "golang.zx2c4.com/wireguard/tun/wintun/nci"
-       registryEx "golang.zx2c4.com/wireguard/tun/wintun/registry"
-       "golang.zx2c4.com/wireguard/tun/wintun/setupapi"
 )
 
-type Pool string
-
-type Interface struct {
-       cfgInstanceID windows.GUID
-       devInstanceID string
-       luidIndex     uint32
-       ifType        uint32
-       pool          Pool
-}
-
-var deviceClassNetGUID = windows.GUID{Data1: 0x4d36e972, Data2: 0xe325, Data3: 0x11ce, Data4: [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}
-var deviceInterfaceNetGUID = windows.GUID{Data1: 0xcac88484, Data2: 0x7515, Data3: 0x4c03, Data4: [8]byte{0x82, 0xe6, 0x71, 0xa8, 0x7a, 0xba, 0xc3, 0x61}}
+type loggerLevel int
 
 const (
-       hardwareID             = "Wintun"
-       waitForRegistryTimeout = time.Second * 10
+       logInfo loggerLevel = iota
+       logWarn
+       logErr
 )
 
-// makeWintun creates a Wintun interface handle and populates it from the device's registry key.
-func makeWintun(devInfo setupapi.DevInfo, devInfoData *setupapi.DevInfoData, pool Pool) (*Interface, error) {
-       // Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key.
-       key, err := devInfo.OpenDevRegKey(devInfoData, setupapi.DICS_FLAG_GLOBAL, 0, setupapi.DIREG_DRV, registry.QUERY_VALUE)
-       if err != nil {
-               return nil, fmt.Errorf("Device-specific registry key open failed: %v", err)
-       }
-       defer key.Close()
-
-       // Read the NetCfgInstanceId value.
-       valueStr, err := registryEx.GetStringValue(key, "NetCfgInstanceId")
-       if err != nil {
-               return nil, fmt.Errorf("RegQueryStringValue(\"NetCfgInstanceId\") failed: %v", err)
-       }
-
-       // Convert to GUID.
-       ifid, err := windows.GUIDFromString(valueStr)
-       if err != nil {
-               return nil, fmt.Errorf("NetCfgInstanceId registry value is not a GUID (expected: \"{...}\", provided: %q)", valueStr)
-       }
-
-       // Read the NetLuidIndex value.
-       luidIdx, _, err := key.GetIntegerValue("NetLuidIndex")
-       if err != nil {
-               return nil, fmt.Errorf("RegQueryValue(\"NetLuidIndex\") failed: %v", err)
-       }
-
-       // Read the NetLuidIndex value.
-       ifType, _, err := key.GetIntegerValue("*IfType")
-       if err != nil {
-               return nil, fmt.Errorf("RegQueryValue(\"*IfType\") failed: %v", err)
-       }
-
-       instanceID, err := devInfo.DeviceInstanceID(devInfoData)
-       if err != nil {
-               return nil, fmt.Errorf("DeviceInstanceID failed: %v", err)
-       }
-
-       return &Interface{
-               cfgInstanceID: ifid,
-               devInstanceID: instanceID,
-               luidIndex:     uint32(luidIdx),
-               ifType:        uint32(ifType),
-               pool:          pool,
-       }, nil
-}
-
-func removeNumberedSuffix(ifname string) string {
-       removed := strings.TrimRight(ifname, "0123456789")
-       if removed != ifname && len(removed) > 1 && removed[len(removed)-1] == ' ' {
-               return removed[:len(removed)-1]
-       }
-       return ifname
-}
-
-// GetInterface finds a Wintun interface by its name. This function returns
-// the interface if found, or windows.ERROR_OBJECT_NOT_FOUND otherwise. If
-// the interface is found but not a Wintun-class or a member of the pool,
-// this function returns windows.ERROR_ALREADY_EXISTS.
-func (pool Pool) GetInterface(ifname string) (*Interface, error) {
-       mutex, err := pool.takeNameMutex()
-       if err != nil {
-               return nil, err
-       }
-       defer func() {
-               windows.ReleaseMutex(mutex)
-               windows.CloseHandle(mutex)
-       }()
-
-       // Create a list of network devices.
-       devInfo, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
-       if err != nil {
-               return nil, fmt.Errorf("SetupDiGetClassDevsEx(%v) failed: %v", deviceClassNetGUID, err)
-       }
-       defer devInfo.Close()
-
-       // Windows requires each interface to have a different name. When
-       // enforcing this, Windows treats interface names case-insensitive. If an
-       // interface "FooBar" exists and this function reports there is no
-       // interface "foobar", an attempt to create a new interface and name it
-       // "foobar" would cause conflict with "FooBar".
-       ifname = strings.ToLower(ifname)
-
-       for index := 0; ; index++ {
-               devInfoData, err := devInfo.EnumDeviceInfo(index)
-               if err != nil {
-                       if err == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               // Check the Hardware ID to make sure it's a real Wintun device first. This avoids doing slow operations on non-Wintun devices.
-               property, err := devInfo.DeviceRegistryProperty(devInfoData, setupapi.SPDRP_HARDWAREID)
-               if err != nil {
-                       continue
-               }
-               if !isOurHardwareID(property) {
-                       continue
-               }
-
-               wintun, err := makeWintun(devInfo, devInfoData, pool)
-               if err != nil {
-                       continue
-               }
-
-               // TODO: is there a better way than comparing ifnames?
-               ifname2, err := wintun.Name()
-               if err != nil {
-                       continue
-               }
-               ifname2 = strings.ToLower(ifname2)
-               ifname3 := removeNumberedSuffix(ifname2)
-
-               if ifname == ifname2 || ifname == ifname3 {
-                       err = devInfo.BuildDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER)
-                       if err != nil {
-                               return nil, fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
-                       }
-                       defer devInfo.DestroyDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER)
-
-                       for index := 0; ; index++ {
-                               driverData, err := devInfo.EnumDriverInfo(devInfoData, setupapi.SPDIT_COMPATDRIVER, index)
-                               if err != nil {
-                                       if err == windows.ERROR_NO_MORE_ITEMS {
-                                               break
-                                       }
-                                       continue
-                               }
-
-                               // Get driver info details.
-                               driverDetailData, err := devInfo.DriverInfoDetail(devInfoData, driverData)
-                               if err != nil {
-                                       continue
-                               }
-
-                               if driverDetailData.IsCompatible(hardwareID) {
-                                       isMember, err := pool.isMember(devInfo, devInfoData)
-                                       if err != nil {
-                                               return nil, err
-                                       }
-                                       if !isMember {
-                                               return nil, windows.ERROR_ALREADY_EXISTS
-                                       }
-
-                                       return wintun, nil
-                               }
-                       }
+const (
+       PoolNameMax    = 256
+       AdapterNameMax = 128
+)
 
-                       // This interface is not using Wintun driver.
-                       return nil, windows.ERROR_ALREADY_EXISTS
-               }
-       }
+type Pool [PoolNameMax]uint16
+type Adapter struct {
+       handle uintptr
+}
+
+var (
+       modwintun = windows.NewLazyDLL("wintun.dll")
+
+       procWintunCreateAdapter           = modwintun.NewProc("WintunCreateAdapter")
+       procWintunDeleteAdapter           = modwintun.NewProc("WintunDeleteAdapter")
+       procWintunDeletePoolDriver        = modwintun.NewProc("WintunDeletePoolDriver")
+       procWintunEnumAdapters            = modwintun.NewProc("WintunEnumAdapters")
+       procWintunFreeAdapter             = modwintun.NewProc("WintunFreeAdapter")
+       procWintunOpenAdapter             = modwintun.NewProc("WintunOpenAdapter")
+       procWintunGetAdapterLUID          = modwintun.NewProc("WintunGetAdapterLUID")
+       procWintunGetAdapterName          = modwintun.NewProc("WintunGetAdapterName")
+       procWintunGetRunningDriverVersion = modwintun.NewProc("WintunGetRunningDriverVersion")
+       procWintunOpenAdapterDeviceObject = modwintun.NewProc("WintunOpenAdapterDeviceObject")
+       procWintunSetAdapterName          = modwintun.NewProc("WintunSetAdapterName")
+       procWintunSetLogger               = modwintun.NewProc("WintunSetLogger")
+)
 
-       return nil, windows.ERROR_OBJECT_NOT_FOUND
+func init() {
+       syscall.Syscall(procWintunSetLogger.Addr(), 1, windows.NewCallback(func(level loggerLevel, msg *uint16) int {
+               log.Println("[Wintun]", windows.UTF16PtrToString(msg))
+               return 0
+       }), 0, 0)
 }
 
-// CreateInterface creates a Wintun interface. ifname is the requested name of
-// the interface, while requestedGUID is the GUID of the created network
-// interface, which then influences NLA generation deterministically. If it is
-// set to nil, the GUID is chosen by the system at random, and hence a new NLA
-// entry is created for each new interface. It is called "requested" GUID
-// because the API it uses is completely undocumented, and so there could be minor
-// interesting complications with its usage. This function returns the network
-// interface ID and a flag if reboot is required.
-func (pool Pool) CreateInterface(ifname string, requestedGUID *windows.GUID) (wintun *Interface, rebootRequired bool, err error) {
-       mutex, err := pool.takeNameMutex()
-       if err != nil {
-               return
-       }
-       defer func() {
-               windows.ReleaseMutex(mutex)
-               windows.CloseHandle(mutex)
-       }()
-
-       // Create an empty device info set for network adapter device class.
-       devInfo, err := setupapi.SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, "")
-       if err != nil {
-               err = fmt.Errorf("SetupDiCreateDeviceInfoListEx(%v) failed: %v", deviceClassNetGUID, err)
-               return
-       }
-       defer devInfo.Close()
-
-       // Get the device class name from GUID.
-       className, err := setupapi.SetupDiClassNameFromGuidEx(&deviceClassNetGUID, "")
-       if err != nil {
-               err = fmt.Errorf("SetupDiClassNameFromGuidEx(%v) failed: %v", deviceClassNetGUID, err)
-               return
-       }
-
-       // Create a new device info element and add it to the device info set.
-       deviceTypeName := pool.deviceTypeName()
-       devInfoData, err := devInfo.CreateDeviceInfo(className, &deviceClassNetGUID, deviceTypeName, 0, setupapi.DICD_GENERATE_ID)
+func MakePool(poolName string) (pool *Pool, err error) {
+       poolName16, err := windows.UTF16FromString(poolName)
        if err != nil {
-               err = fmt.Errorf("SetupDiCreateDeviceInfo failed: %v", err)
                return
        }
-
-       err = setQuietInstall(devInfo, devInfoData)
-       if err != nil {
-               err = fmt.Errorf("Setting quiet installation failed: %v", err)
-               return
-       }
-
-       // Set a device information element as the selected member of a device information set.
-       err = devInfo.SetSelectedDevice(devInfoData)
-       if err != nil {
-               err = fmt.Errorf("SetupDiSetSelectedDevice failed: %v", err)
-               return
-       }
-
-       // Set Plug&Play device hardware ID property.
-       err = devInfo.SetDeviceRegistryPropertyString(devInfoData, setupapi.SPDRP_HARDWAREID, hardwareID)
-       if err != nil {
-               err = fmt.Errorf("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: %v", err)
-               return
-       }
-
-       err = devInfo.BuildDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER) // TODO: This takes ~510ms
-       if err != nil {
-               err = fmt.Errorf("SetupDiBuildDriverInfoList failed: %v", err)
-               return
-       }
-       defer devInfo.DestroyDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER)
-
-       driverDate := windows.Filetime{}
-       driverVersion := uint64(0)
-       for index := 0; ; index++ { // TODO: This loop takes ~600ms
-               driverData, err := devInfo.EnumDriverInfo(devInfoData, setupapi.SPDIT_COMPATDRIVER, index)
-               if err != nil {
-                       if err == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               // Check the driver version first, since the check is trivial and will save us iterating over hardware IDs for any driver versioned prior our best match.
-               if driverData.IsNewer(driverDate, driverVersion) {
-                       driverDetailData, err := devInfo.DriverInfoDetail(devInfoData, driverData)
-                       if err != nil {
-                               continue
-                       }
-
-                       if driverDetailData.IsCompatible(hardwareID) {
-                               err := devInfo.SetSelectedDriver(devInfoData, driverData)
-                               if err != nil {
-                                       continue
-                               }
-
-                               driverDate = driverData.DriverDate
-                               driverVersion = driverData.DriverVersion
-                       }
-               }
-       }
-
-       if driverVersion == 0 {
-               err = fmt.Errorf("No driver for device %q installed", hardwareID)
-               return
-       }
-
-       defer func() {
-               if err != nil {
-                       // The interface failed to install, or the interface ID was unobtainable. Clean-up.
-                       removeDeviceParams := setupapi.RemoveDeviceParams{
-                               ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE),
-                               Scope:              setupapi.DI_REMOVEDEVICE_GLOBAL,
-                       }
-
-                       // Set class installer parameters for DIF_REMOVE.
-                       if devInfo.SetClassInstallParams(devInfoData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams))) == nil {
-                               // Call appropriate class installer.
-                               if devInfo.CallClassInstaller(setupapi.DIF_REMOVE, devInfoData) == nil {
-                                       rebootRequired = rebootRequired || checkReboot(devInfo, devInfoData)
-                               }
-                       }
-
-                       wintun = nil
-               }
-       }()
-
-       // Call appropriate class installer.
-       err = devInfo.CallClassInstaller(setupapi.DIF_REGISTERDEVICE, devInfoData)
-       if err != nil {
-               err = fmt.Errorf("SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed: %v", err)
-               return
-       }
-
-       // Register device co-installers if any. (Ignore errors)
-       devInfo.CallClassInstaller(setupapi.DIF_REGISTER_COINSTALLERS, devInfoData)
-
-       var netDevRegKey registry.Key
-       const pollTimeout = time.Millisecond * 50
-       for i := 0; i < int(waitForRegistryTimeout/pollTimeout); i++ {
-               if i != 0 {
-                       time.Sleep(pollTimeout)
-               }
-               netDevRegKey, err = devInfo.OpenDevRegKey(devInfoData, setupapi.DICS_FLAG_GLOBAL, 0, setupapi.DIREG_DRV, registry.SET_VALUE|registry.QUERY_VALUE|registry.NOTIFY)
-               if err == nil {
-                       break
-               }
-       }
-       if err != nil {
-               err = fmt.Errorf("SetupDiOpenDevRegKey failed: %v", err)
-               return
-       }
-       defer netDevRegKey.Close()
-       if requestedGUID != nil {
-               err = netDevRegKey.SetStringValue("NetSetupAnticipatedInstanceId", requestedGUID.String())
-               if err != nil {
-                       err = fmt.Errorf("SetStringValue(NetSetupAnticipatedInstanceId) failed: %v", err)
-                       return
-               }
-       }
-
-       // Install interfaces if any. (Ignore errors)
-       devInfo.CallClassInstaller(setupapi.DIF_INSTALLINTERFACES, devInfoData)
-
-       // Install the device.
-       err = devInfo.CallClassInstaller(setupapi.DIF_INSTALLDEVICE, devInfoData)
-       if err != nil {
-               err = fmt.Errorf("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed: %v", err)
-               return
-       }
-       rebootRequired = checkReboot(devInfo, devInfoData)
-
-       err = devInfo.SetDeviceRegistryPropertyString(devInfoData, setupapi.SPDRP_DEVICEDESC, deviceTypeName)
-       if err != nil {
-               err = fmt.Errorf("SetDeviceRegistryPropertyString(SPDRP_DEVICEDESC) failed: %v", err)
+       if len(poolName16) > PoolNameMax {
+               err = errors.New("Pool name too long")
                return
        }
+       pool = &Pool{}
+       copy(pool[:], poolName16)
+       return
+}
 
-       // 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.
-       _, err = registryEx.GetStringValueWait(netDevRegKey, "NetCfgInstanceId", waitForRegistryTimeout)
-       if err != nil {
-               err = fmt.Errorf("GetStringValueWait(NetCfgInstanceId) failed: %v", err)
-               return
-       }
-       _, err = registryEx.GetIntegerValueWait(netDevRegKey, "NetLuidIndex", waitForRegistryTimeout)
-       if err != nil {
-               err = fmt.Errorf("GetIntegerValueWait(NetLuidIndex) failed: %v", err)
-               return
-       }
-       _, err = registryEx.GetIntegerValueWait(netDevRegKey, "*IfType", waitForRegistryTimeout)
-       if err != nil {
-               err = fmt.Errorf("GetIntegerValueWait(*IfType) failed: %v", err)
-               return
-       }
+func (pool *Pool) String() string {
+       return windows.UTF16ToString(pool[:])
+}
 
-       // Get network interface.
-       wintun, err = makeWintun(devInfo, devInfoData, pool)
-       if err != nil {
-               err = fmt.Errorf("makeWintun failed: %v", err)
-               return
-       }
+func freeAdapter(wintun *Adapter) {
+       syscall.Syscall(procWintunFreeAdapter.Addr(), 1, uintptr(wintun.handle), 0, 0)
+}
 
-       // Wait for TCP/IP adapter registry key to emerge and populate.
-       tcpipAdapterRegKey, err := registryEx.OpenKeyWait(
-               registry.LOCAL_MACHINE,
-               wintun.tcpipAdapterRegKeyName(), registry.QUERY_VALUE|registry.NOTIFY,
-               waitForRegistryTimeout)
+// OpenAdapter finds a Wintun adapter by its name. This function returns the adapter if found, or
+// windows.ERROR_FILE_NOT_FOUND otherwise. If the adapter is found but not a Wintun-class or a
+// member of the pool, this function returns windows.ERROR_ALREADY_EXISTS. The adapter must be
+// released after use.
+func (pool *Pool) OpenAdapter(ifname string) (wintun *Adapter, err error) {
+       ifname16, err := windows.UTF16PtrFromString(ifname)
        if err != nil {
-               err = fmt.Errorf("OpenKeyWait(HKLM\\%s) failed: %v", wintun.tcpipAdapterRegKeyName(), err)
-               return
-       }
-       defer tcpipAdapterRegKey.Close()
-       _, err = registryEx.GetStringValueWait(tcpipAdapterRegKey, "IpConfig", waitForRegistryTimeout)
-       if err != nil {
-               err = fmt.Errorf("GetStringValueWait(IpConfig) failed: %v", err)
-               return
+               return nil, err
        }
-
-       tcpipInterfaceRegKeyName, err := wintun.tcpipInterfaceRegKeyName()
-       if err != nil {
-               err = fmt.Errorf("tcpipInterfaceRegKeyName failed: %v", err)
+       r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 2, uintptr(unsafe.Pointer(pool)), uintptr(unsafe.Pointer(ifname16)), 0)
+       if r0 == 0 {
+               err = e1
                return
        }
+       wintun = &Adapter{r0}
+       runtime.SetFinalizer(wintun, freeAdapter)
+       return
+}
 
-       // Wait for TCP/IP interface registry key to emerge.
-       tcpipInterfaceRegKey, err := registryEx.OpenKeyWait(
-               registry.LOCAL_MACHINE,
-               tcpipInterfaceRegKeyName, registry.QUERY_VALUE|registry.SET_VALUE,
-               waitForRegistryTimeout)
+// CreateAdapter creates a Wintun adapter. ifname is the requested name of the adapter, while
+// requestedGUID is the GUID of the created network adapter, which then influences NLA generation
+// deterministically. If it is set to nil, the GUID is chosen by the system at random, and hence a
+// new NLA entry is created for each new adapter. It is called "requested" GUID because the API it
+// uses is completely undocumented, and so there could be minor interesting complications with its
+// usage. This function returns the network adapter ID and a flag if reboot is required.
+func (pool *Pool) CreateAdapter(ifname string, requestedGUID *windows.GUID) (wintun *Adapter, rebootRequired bool, err error) {
+       var ifname16 *uint16
+       ifname16, err = windows.UTF16PtrFromString(ifname)
        if err != nil {
-               err = fmt.Errorf("OpenKeyWait(HKLM\\%s) failed: %v", tcpipInterfaceRegKeyName, err)
                return
        }
-       defer tcpipInterfaceRegKey.Close()
-       // Disable dead gateway detection on our interface.
-       tcpipInterfaceRegKey.SetDWordValue("EnableDeadGWDetect", 0)
-
-       err = wintun.SetName(ifname)
-       if err != nil {
-               err = fmt.Errorf("Unable to set name of Wintun interface: %v", err)
+       var _p0 uint32
+       r0, _, e1 := syscall.Syscall6(procWintunCreateAdapter.Addr(), 4, uintptr(unsafe.Pointer(pool)), uintptr(unsafe.Pointer(ifname16)), uintptr(unsafe.Pointer(requestedGUID)), uintptr(unsafe.Pointer(&_p0)), 0, 0)
+       rebootRequired = _p0 != 0
+       if r0 == 0 {
+               err = e1
                return
        }
-
+       wintun = &Adapter{r0}
+       runtime.SetFinalizer(wintun, freeAdapter)
        return
 }
 
-// DeleteInterface deletes a Wintun interface. This function succeeds
-// if the interface was not found. It returns a bool indicating whether
-// a reboot is required.
-func (wintun *Interface) DeleteInterface() (rebootRequired bool, err error) {
-       devInfo, devInfoData, err := wintun.devInfoData()
-       if err == windows.ERROR_OBJECT_NOT_FOUND {
-               return false, nil
+// Delete deletes a Wintun adapter. This function succeeds if the adapter was not found. It returns
+// a bool indicating whether a reboot is required.
+func (wintun *Adapter) Delete(forceCloseSessions bool) (rebootRequired bool, err error) {
+       var _p0 uint32
+       if forceCloseSessions {
+               _p0 = 1
        }
-       if err != nil {
-               return false, err
+       var _p1 uint32
+       r1, _, e1 := syscall.Syscall(procWintunDeleteAdapter.Addr(), 3, uintptr(wintun.handle), uintptr(_p0), uintptr(unsafe.Pointer(&_p1)))
+       rebootRequired = _p1 != 0
+       if r1 == 0 {
+               err = e1
        }
-       defer devInfo.Close()
-
-       // Remove the device.
-       removeDeviceParams := setupapi.RemoveDeviceParams{
-               ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE),
-               Scope:              setupapi.DI_REMOVEDEVICE_GLOBAL,
-       }
-
-       // Set class installer parameters for DIF_REMOVE.
-       err = devInfo.SetClassInstallParams(devInfoData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams)))
-       if err != nil {
-               return false, fmt.Errorf("SetupDiSetClassInstallParams failed: %v", err)
-       }
-
-       // Call appropriate class installer.
-       err = devInfo.CallClassInstaller(setupapi.DIF_REMOVE, devInfoData)
-       if err != nil {
-               return false, fmt.Errorf("SetupDiCallClassInstaller failed: %v", err)
-       }
-
-       return checkReboot(devInfo, devInfoData), nil
+       return
 }
 
-// DeleteMatchingInterfaces deletes all Wintun interfaces, which match
+// DeleteMatchingAdapters deletes all Wintun adapters, which match
 // given criteria, and returns which ones it deleted, whether a reboot
 // is required after, and which errors occurred during the process.
-func (pool Pool) DeleteMatchingInterfaces(matches func(wintun *Interface) bool) (deviceInstancesDeleted []uint32, rebootRequired bool, errors []error) {
-       mutex, err := pool.takeNameMutex()
-       if err != nil {
-               errors = append(errors, err)
-               return
-       }
-       defer func() {
-               windows.ReleaseMutex(mutex)
-               windows.CloseHandle(mutex)
-       }()
-
-       devInfo, 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 devInfo.Close()
-
-       for i := 0; ; i++ {
-               devInfoData, err := devInfo.EnumDeviceInfo(i)
-               if err != nil {
-                       if err == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
+func (pool *Pool) DeleteMatchingAdapters(matches func(adapter *Adapter) bool, forceCloseSessions bool) (rebootRequired bool, errors []error) {
+       cb := func(handle uintptr, _ uintptr) int {
+               adapter := &Adapter{handle}
+               if !matches(adapter) {
+                       return 1
                }
-
-               // Check the Hardware ID to make sure it's a real Wintun device first. This avoids doing slow operations on non-Wintun devices.
-               property, err := devInfo.DeviceRegistryProperty(devInfoData, setupapi.SPDRP_HARDWAREID)
-               if err != nil {
-                       continue
-               }
-               if !isOurHardwareID(property) {
-                       continue
-               }
-
-               err = devInfo.BuildDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER)
-               if err != nil {
-                       continue
-               }
-               defer devInfo.DestroyDriverInfoList(devInfoData, setupapi.SPDIT_COMPATDRIVER)
-
-               isWintun := false
-               for j := 0; ; j++ {
-                       driverData, err := devInfo.EnumDriverInfo(devInfoData, setupapi.SPDIT_COMPATDRIVER, j)
-                       if err != nil {
-                               if err == windows.ERROR_NO_MORE_ITEMS {
-                                       break
-                               }
-                               continue
-                       }
-                       driverDetailData, err := devInfo.DriverInfoDetail(devInfoData, driverData)
-                       if err != nil {
-                               continue
-                       }
-                       if driverDetailData.IsCompatible(hardwareID) {
-                               isWintun = true
-                               break
-                       }
-               }
-               if !isWintun {
-                       continue
-               }
-
-               isMember, err := pool.isMember(devInfo, devInfoData)
-               if err != nil {
-                       errors = append(errors, err)
-                       continue
-               }
-               if !isMember {
-                       continue
-               }
-
-               wintun, err := makeWintun(devInfo, devInfoData, pool)
-               if err != nil {
-                       errors = append(errors, fmt.Errorf("Unable to make Wintun interface object: %v", err))
-                       continue
-               }
-               if !matches(wintun) {
-                       continue
-               }
-
-               err = setQuietInstall(devInfo, devInfoData)
+               rebootRequired2, err := adapter.Delete(forceCloseSessions)
                if err != nil {
                        errors = append(errors, err)
-                       continue
+                       return 1
                }
-
-               inst := devInfoData.DevInst
-               removeDeviceParams := setupapi.RemoveDeviceParams{
-                       ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE),
-                       Scope:              setupapi.DI_REMOVEDEVICE_GLOBAL,
-               }
-               err = devInfo.SetClassInstallParams(devInfoData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams)))
-               if err != nil {
-                       errors = append(errors, err)
-                       continue
-               }
-               err = devInfo.CallClassInstaller(setupapi.DIF_REMOVE, devInfoData)
-               if err != nil {
-                       errors = append(errors, err)
-                       continue
-               }
-               rebootRequired = rebootRequired || checkReboot(devInfo, devInfoData)
-               deviceInstancesDeleted = append(deviceInstancesDeleted, inst)
+               rebootRequired = rebootRequired || rebootRequired2
+               return 1
+       }
+       r1, _, e1 := syscall.Syscall(procWintunEnumAdapters.Addr(), 3, uintptr(unsafe.Pointer(pool)), uintptr(windows.NewCallback(cb)), 0)
+       if r1 == 0 {
+               errors = append(errors, e1)
        }
        return
 }
 
-// isMember checks if SPDRP_DEVICEDESC or SPDRP_FRIENDLYNAME match device type name.
-func (pool Pool) isMember(devInfo setupapi.DevInfo, devInfoData *setupapi.DevInfoData) (bool, error) {
-       deviceDescVal, err := devInfo.DeviceRegistryProperty(devInfoData, setupapi.SPDRP_DEVICEDESC)
-       if err != nil {
-               return false, fmt.Errorf("DeviceRegistryPropertyString(SPDRP_DEVICEDESC) failed: %v", err)
-       }
-       deviceDesc, _ := deviceDescVal.(string)
-       friendlyNameVal, err := devInfo.DeviceRegistryProperty(devInfoData, setupapi.SPDRP_FRIENDLYNAME)
-       if err != nil {
-               return false, fmt.Errorf("DeviceRegistryPropertyString(SPDRP_FRIENDLYNAME) failed: %v", err)
+// Name returns the name of the Wintun adapter.
+func (wintun *Adapter) Name() (ifname string, err error) {
+       var ifname16 [AdapterNameMax]uint16
+       r1, _, e1 := syscall.Syscall(procWintunGetAdapterName.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&ifname16[0])), 0)
+       if r1 == 0 {
+               err = e1
+               return
        }
-       friendlyName, _ := friendlyNameVal.(string)
-       deviceTypeName := pool.deviceTypeName()
-       return friendlyName == deviceTypeName || deviceDesc == deviceTypeName ||
-               removeNumberedSuffix(friendlyName) == deviceTypeName || removeNumberedSuffix(deviceDesc) == deviceTypeName, nil
+       ifname = windows.UTF16ToString(ifname16[:])
+       return
 }
 
-// checkReboot checks device install parameters if a system reboot is required.
-func checkReboot(devInfo setupapi.DevInfo, devInfoData *setupapi.DevInfoData) bool {
-       devInstallParams, err := devInfo.DeviceInstallParams(devInfoData)
-       if err != nil {
-               return false
+// DeleteDriver deletes all Wintun adapters in a pool and if there are no more adapters in any other
+// pools, also removes Wintun from the driver store, usually called by uninstallers.
+func (pool *Pool) DeleteDriver() (rebootRequired bool, err error) {
+       var _p0 uint32
+       r1, _, e1 := syscall.Syscall(procWintunDeletePoolDriver.Addr(), 2, uintptr(unsafe.Pointer(pool)), uintptr(unsafe.Pointer(&_p0)), 0)
+       rebootRequired = _p0 != 0
+       if r1 == 0 {
+               err = e1
        }
+       return
 
-       return (devInstallParams.Flags & (setupapi.DI_NEEDREBOOT | setupapi.DI_NEEDRESTART)) != 0
 }
 
-// setQuietInstall sets device install parameters for a quiet installation
-func setQuietInstall(devInfo setupapi.DevInfo, devInfoData *setupapi.DevInfoData) error {
-       devInstallParams, err := devInfo.DeviceInstallParams(devInfoData)
+// SetName sets name of the Wintun adapter.
+func (wintun *Adapter) SetName(ifname string) (err error) {
+       ifname16, err := windows.UTF16FromString(ifname)
        if err != nil {
                return err
        }
-
-       devInstallParams.Flags |= setupapi.DI_QUIETINSTALL
-       return devInfo.SetDeviceInstallParams(devInfoData, devInstallParams)
-}
-
-// deviceTypeName returns pool-specific device type name.
-func (pool Pool) deviceTypeName() string {
-       return fmt.Sprintf("%s Tunnel", pool)
-}
-
-// Name returns the name of the Wintun interface.
-func (wintun *Interface) Name() (string, error) {
-       return nci.ConnectionName(&wintun.cfgInstanceID)
-}
-
-// SetName sets name of the Wintun interface.
-func (wintun *Interface) SetName(ifname string) error {
-       const maxSuffix = 1000
-       availableIfname := ifname
-       for i := 0; ; i++ {
-               err := nci.SetConnectionName(&wintun.cfgInstanceID, availableIfname)
-               if err == windows.ERROR_DUP_NAME {
-                       duplicateGuid, err2 := iphlpapi.InterfaceGUIDFromAlias(availableIfname)
-                       if err2 == nil {
-                               for j := 0; j < maxSuffix; j++ {
-                                       proposal := fmt.Sprintf("%s %d", ifname, j+1)
-                                       if proposal == availableIfname {
-                                               continue
-                                       }
-                                       err2 = nci.SetConnectionName(duplicateGuid, proposal)
-                                       if err2 == windows.ERROR_DUP_NAME {
-                                               continue
-                                       }
-                                       if err2 == nil {
-                                               err = nci.SetConnectionName(&wintun.cfgInstanceID, availableIfname)
-                                               if err == nil {
-                                                       break
-                                               }
-                                       }
-                                       break
-                               }
-                       }
-               }
-               if err == nil {
-                       break
-               }
-
-               if i > maxSuffix || err != windows.ERROR_DUP_NAME {
-                       return fmt.Errorf("NciSetConnectionName failed: %v", err)
-               }
-               availableIfname = fmt.Sprintf("%s %d", ifname, i+1)
-       }
-
-       // TODO: This should use NetSetup2 so that it doesn't get unset.
-       deviceRegKey, err := registry.OpenKey(registry.LOCAL_MACHINE, wintun.deviceRegKeyName(), registry.SET_VALUE)
-       if err != nil {
-               return fmt.Errorf("Device-level registry key open failed: %v", err)
+       r1, _, e1 := syscall.Syscall(procWintunSetAdapterName.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&ifname16[0])), 0)
+       if r1 == 0 {
+               err = e1
        }
-       defer deviceRegKey.Close()
-       err = deviceRegKey.SetStringValue("FriendlyName", wintun.pool.deviceTypeName())
-       if err != nil {
-               return fmt.Errorf("SetStringValue(FriendlyName) failed: %v", err)
-       }
-       return nil
-}
-
-// tcpipAdapterRegKeyName returns the adapter-specific TCP/IP network registry key name.
-func (wintun *Interface) tcpipAdapterRegKeyName() string {
-       return fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%v", wintun.cfgInstanceID)
-}
-
-// deviceRegKeyName returns the device-level registry key name.
-func (wintun *Interface) deviceRegKeyName() string {
-       return fmt.Sprintf("SYSTEM\\CurrentControlSet\\Enum\\%v", wintun.devInstanceID)
-}
-
-// Version returns the version of the Wintun driver and NDIS system currently loaded.
-func (wintun *Interface) Version() (driverVersion string, ndisVersion string, err error) {
-       key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Wintun", registry.QUERY_VALUE)
-       if err != nil {
-               return
-       }
-       defer key.Close()
-       driverMajor, _, err := key.GetIntegerValue("DriverMajorVersion")
-       if err != nil {
-               return
-       }
-       driverMinor, _, err := key.GetIntegerValue("DriverMinorVersion")
-       if err != nil {
-               return
-       }
-       ndisMajor, _, err := key.GetIntegerValue("NdisMajorVersion")
-       if err != nil {
-               return
-       }
-       ndisMinor, _, err := key.GetIntegerValue("NdisMinorVersion")
-       if err != nil {
-               return
-       }
-       driverVersion = fmt.Sprintf("%d.%d", driverMajor, driverMinor)
-       ndisVersion = fmt.Sprintf("%d.%d", ndisMajor, ndisMinor)
        return
 }
 
-// tcpipInterfaceRegKeyName returns the interface-specific TCP/IP network registry key name.
-func (wintun *Interface) tcpipInterfaceRegKeyName() (path string, err error) {
-       key, err := registry.OpenKey(registry.LOCAL_MACHINE, wintun.tcpipAdapterRegKeyName(), registry.QUERY_VALUE)
-       if err != nil {
-               return "", fmt.Errorf("Error opening adapter-specific TCP/IP network registry key: %v", err)
-       }
-       paths, _, err := key.GetStringsValue("IpConfig")
-       key.Close()
-       if err != nil {
-               return "", fmt.Errorf("Error reading IpConfig registry key: %v", err)
-       }
-       if len(paths) == 0 {
-               return "", errors.New("No TCP/IP interfaces found on adapter")
-       }
-       return fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), nil
-}
-
-// devInfoData returns TUN device info list handle and interface device info
-// data. The device info list handle must be closed after use. In case the
-// device is not found, windows.ERROR_OBJECT_NOT_FOUND is returned.
-func (wintun *Interface) devInfoData() (setupapi.DevInfo, *setupapi.DevInfoData, error) {
-       // Create a list of network devices.
-       devInfo, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
-       if err != nil {
-               return 0, nil, fmt.Errorf("SetupDiGetClassDevsEx(%v) failed: %v", deviceClassNetGUID, err.Error())
-       }
-
-       for index := 0; ; index++ {
-               devInfoData, err := devInfo.EnumDeviceInfo(index)
-               if err != nil {
-                       if err == windows.ERROR_NO_MORE_ITEMS {
-                               break
-                       }
-                       continue
-               }
-
-               // Get interface ID.
-               // TODO: Store some ID in the Wintun object such that this call isn't required.
-               wintun2, err := makeWintun(devInfo, devInfoData, wintun.pool)
-               if err != nil {
-                       continue
-               }
-
-               if wintun.cfgInstanceID == wintun2.cfgInstanceID {
-                       err = setQuietInstall(devInfo, devInfoData)
-                       if err != nil {
-                               devInfo.Close()
-                               return 0, nil, fmt.Errorf("Setting quiet installation failed: %v", err)
-                       }
-                       return devInfo, devInfoData, nil
-               }
+// RunningVersion returns the version of the running Wintun driver.
+func RunningVersion() (version uint32, err error) {
+       r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0)
+       version = uint32(r0)
+       if version == 0 {
+               err = e1
        }
-
-       devInfo.Close()
-       return 0, nil, windows.ERROR_OBJECT_NOT_FOUND
+       return
 }
 
-// handle returns a handle to the interface device object.
-func (wintun *Interface) handle() (windows.Handle, error) {
-       interfaces, err := setupapi.CM_Get_Device_Interface_List(wintun.devInstanceID, &deviceInterfaceNetGUID, setupapi.CM_GET_DEVICE_INTERFACE_LIST_PRESENT)
-       if err != nil {
-               return windows.InvalidHandle, fmt.Errorf("Error listing NDIS interfaces: %v", err)
+// handle returns a handle to the adapter device object. Release handle with windows.CloseHandle
+func (wintun *Adapter) OpenAdapterDeviceObject() (handle windows.Handle, err error) {
+       r0, _, e1 := syscall.Syscall(procWintunOpenAdapterDeviceObject.Addr(), 1, uintptr(wintun.handle), 0, 0)
+       handle = windows.Handle(r0)
+       if handle == windows.InvalidHandle {
+               err = e1
        }
-       handle, err := windows.CreateFile(windows.StringToUTF16Ptr(interfaces[0]), windows.GENERIC_READ|windows.GENERIC_WRITE, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, nil, windows.OPEN_EXISTING, 0, 0)
-       if err != nil {
-               return windows.InvalidHandle, fmt.Errorf("Error opening NDIS device: %v", err)
-       }
-       return handle, nil
-}
-
-// GUID returns the GUID of the interface.
-func (wintun *Interface) GUID() windows.GUID {
-       return wintun.cfgInstanceID
-}
-
-// LUID returns the LUID of the interface.
-func (wintun *Interface) LUID() uint64 {
-       return ((uint64(wintun.luidIndex) & ((1 << 24) - 1)) << 24) | ((uint64(wintun.ifType) & ((1 << 16) - 1)) << 48)
+       return
 }
 
-func isOurHardwareID(property interface{}) bool {
-       hwidLC := strings.ToLower(hardwareID)
-
-       if hwids, ok := property.([]string); ok && len(hwids) > 0 {
-               for i := range hwids {
-                       if strings.ToLower(hwids[i]) == hwidLC {
-                               return true
-                       }
-               }
-       }
-       if hwid, ok := property.(string); ok && strings.ToLower(hwid) == hwidLC {
-               return true
-       }
-
-       return false
+// LUID returns the LUID of the adapter.
+func (wintun *Adapter) LUID() (luid uint64) {
+       syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0)
+       return
 }