mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
wgengine/winnet: invoke some COM methods directly instead of through IDispatch.
Intermittently in the wild we are seeing failures when calling `INetworkConnection::GetNetwork`. It is unclear what the root cause is, but what is clear is that the error is happening inside the object's `IDispatch` invoker (as opposed to the method implementation itself). This patch replaces our wrapper for `INetworkConnection::GetNetwork` with an alternate implementation that directly invokes the method, instead of using `IDispatch`. I also replaced the implementations of `INetwork::SetCategory` and `INetwork::GetCategory` while I was there. This patch is speculative and tightly-scoped so that we could possibly add it to a dot-release if necessary. Updates https://github.com/tailscale/tailscale/issues/4134 Updates https://github.com/tailscale/tailscale/issues/6037 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
parent
4021ae6b9d
commit
a44687e71f
@ -9,6 +9,7 @@
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-ole/go-ole"
|
||||
@ -45,6 +46,23 @@ 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 {
|
||||
@ -124,16 +142,35 @@ func (n *INetwork) GetName() (string, error) {
|
||||
}
|
||||
|
||||
func (n *INetwork) GetCategory() (int32, error) {
|
||||
v, err := n.CallMethod("GetCategory")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
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 v.Value().(int32), err
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (n *INetwork) SetCategory(v uint32) error {
|
||||
_, err := n.CallMethod("SetCategory", v)
|
||||
return err
|
||||
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 {
|
||||
@ -141,17 +178,16 @@ func (v *INetworkConnection) VTable() *INetworkConnectionVtbl {
|
||||
}
|
||||
|
||||
func (v *INetworkConnection) GetNetwork() (*INetwork, error) {
|
||||
nraw, err := v.CallMethod("GetNetwork")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
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)
|
||||
}
|
||||
|
||||
n := nraw.ToIDispatch()
|
||||
if n == nil {
|
||||
return nil, fmt.Errorf("GetNetwork: nil IDispatch")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return (*INetwork)(unsafe.Pointer(n)), nil
|
||||
return result, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user