| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- //go:build windows
- package winnet
- import (
- "fmt"
- "syscall"
- "unsafe"
- "github.com/go-ole/go-ole"
- "github.com/go-ole/go-ole/oleutil"
- )
- const CLSID_NetworkListManager = "{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"
- var IID_INetwork = ole.NewGUID("{8A40A45D-055C-4B62-ABD7-6D613E2CEAEC}")
- var IID_INetworkConnection = ole.NewGUID("{DCB00005-570F-4A9B-8D69-199FDBA5723B}")
- type NetworkListManager struct {
- d *ole.Dispatch
- }
- type INetworkConnection struct {
- ole.IDispatch
- }
- type ConnectionList []*INetworkConnection
- type INetworkConnectionVtbl struct {
- ole.IDispatchVtbl
- GetNetwork uintptr
- Get_IsConnectedToInternet uintptr
- Get_IsConnected uintptr
- GetConnectivity uintptr
- GetConnectionId uintptr
- GetAdapterId uintptr
- GetDomainType uintptr
- }
- type INetwork struct {
- ole.IDispatch
- }
- type INetworkVtbl struct {
- ole.IDispatchVtbl
- GetName uintptr
- SetName uintptr
- GetDescription uintptr
- SetDescription uintptr
- GetNetworkId uintptr
- GetDomainType uintptr
- GetNetworkConnections uintptr
- GetTimeCreatedAndConnected uintptr
- Get_IsConnectedToInternet uintptr
- Get_IsConnected uintptr
- GetConnectivity uintptr
- GetCategory uintptr
- SetCategory uintptr
- }
- func NewNetworkListManager(c *ole.Connection) (*NetworkListManager, error) {
- err := c.Create(CLSID_NetworkListManager)
- if err != nil {
- return nil, err
- }
- defer c.Release()
- d, err := c.Dispatch()
- if err != nil {
- return nil, err
- }
- return &NetworkListManager{
- d: d,
- }, nil
- }
- func (m *NetworkListManager) Release() {
- m.d.Release()
- }
- func (cl ConnectionList) Release() {
- for _, v := range cl {
- v.Release()
- }
- }
- func asIID(u ole.UnknownLike, iid *ole.GUID) (*ole.IDispatch, error) {
- if u == nil {
- return nil, fmt.Errorf("asIID: nil UnknownLike")
- }
- d, err := u.QueryInterface(iid)
- u.Release()
- if err != nil {
- return nil, err
- }
- return d, nil
- }
- func (m *NetworkListManager) GetNetworkConnections() (ConnectionList, error) {
- ncraw, err := m.d.Call("GetNetworkConnections")
- if err != nil {
- return nil, err
- }
- nli := ncraw.ToIDispatch()
- if nli == nil {
- return nil, fmt.Errorf("GetNetworkConnections: not IDispatch")
- }
- cl := ConnectionList{}
- err = oleutil.ForEach(nli, func(v *ole.VARIANT) error {
- nc, err := asIID(v.ToIUnknown(), IID_INetworkConnection)
- if err != nil {
- return err
- }
- nco := (*INetworkConnection)(unsafe.Pointer(nc))
- cl = append(cl, nco)
- return nil
- })
- if err != nil {
- cl.Release()
- return nil, err
- }
- return cl, nil
- }
- func (n *INetwork) GetName() (string, error) {
- v, err := n.CallMethod("GetName")
- if err != nil {
- return "", err
- }
- return v.ToString(), err
- }
- func (n *INetwork) GetCategory() (int32, error) {
- var result int32
- r, _, _ := syscall.SyscallN(
- n.VTable().GetCategory,
- uintptr(unsafe.Pointer(n)),
- uintptr(unsafe.Pointer(&result)),
- )
- if int32(r) < 0 {
- return 0, ole.NewError(r)
- }
- return result, nil
- }
- func (n *INetwork) SetCategory(v int32) error {
- r, _, _ := syscall.SyscallN(
- n.VTable().SetCategory,
- uintptr(unsafe.Pointer(n)),
- uintptr(v),
- )
- if int32(r) < 0 {
- return ole.NewError(r)
- }
- return nil
- }
- func (n *INetwork) VTable() *INetworkVtbl {
- return (*INetworkVtbl)(unsafe.Pointer(n.RawVTable))
- }
- func (v *INetworkConnection) VTable() *INetworkConnectionVtbl {
- return (*INetworkConnectionVtbl)(unsafe.Pointer(v.RawVTable))
- }
- func (v *INetworkConnection) GetNetwork() (*INetwork, error) {
- var result *INetwork
- r, _, _ := syscall.SyscallN(
- v.VTable().GetNetwork,
- uintptr(unsafe.Pointer(v)),
- uintptr(unsafe.Pointer(&result)),
- )
- if int32(r) < 0 {
- return nil, ole.NewError(r)
- }
- return result, nil
- }
|