mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-26 03:25:35 +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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/go-ole/go-ole"
|
"github.com/go-ole/go-ole"
|
||||||
@ -45,6 +46,23 @@ type INetwork struct {
|
|||||||
ole.IDispatch
|
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) {
|
func NewNetworkListManager(c *ole.Connection) (*NetworkListManager, error) {
|
||||||
err := c.Create(CLSID_NetworkListManager)
|
err := c.Create(CLSID_NetworkListManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -124,16 +142,35 @@ func (n *INetwork) GetName() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *INetwork) GetCategory() (int32, error) {
|
func (n *INetwork) GetCategory() (int32, error) {
|
||||||
v, err := n.CallMethod("GetCategory")
|
var result int32
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
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 {
|
func (n *INetwork) SetCategory(v int32) error {
|
||||||
_, err := n.CallMethod("SetCategory", v)
|
r, _, _ := syscall.SyscallN(
|
||||||
return err
|
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 {
|
func (v *INetworkConnection) VTable() *INetworkConnectionVtbl {
|
||||||
@ -141,17 +178,16 @@ func (v *INetworkConnection) VTable() *INetworkConnectionVtbl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *INetworkConnection) GetNetwork() (*INetwork, error) {
|
func (v *INetworkConnection) GetNetwork() (*INetwork, error) {
|
||||||
nraw, err := v.CallMethod("GetNetwork")
|
var result *INetwork
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
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()
|
return result, nil
|
||||||
if n == nil {
|
|
||||||
return nil, fmt.Errorf("GetNetwork: nil IDispatch")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return (*INetwork)(unsafe.Pointer(n)), nil
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user