github.com/tailscale/wireguard-go@v0.0.20201119-0.20210522003738-46b531feb08a/tun/wintun/dll_windows.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package wintun 7 8 import ( 9 "fmt" 10 "sync" 11 "sync/atomic" 12 "unsafe" 13 ) 14 15 func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL { 16 return &lazyDLL{Name: name, onLoad: onLoad} 17 } 18 19 func (d *lazyDLL) NewProc(name string) *lazyProc { 20 return &lazyProc{dll: d, Name: name} 21 } 22 23 type lazyProc struct { 24 Name string 25 mu sync.Mutex 26 dll *lazyDLL 27 addr uintptr 28 } 29 30 func (p *lazyProc) Find() error { 31 if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil { 32 return nil 33 } 34 p.mu.Lock() 35 defer p.mu.Unlock() 36 if p.addr != 0 { 37 return nil 38 } 39 40 err := p.dll.Load() 41 if err != nil { 42 return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err) 43 } 44 addr, err := p.nameToAddr() 45 if err != nil { 46 return fmt.Errorf("Error getting %v address: %w", p.Name, err) 47 } 48 49 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr)) 50 return nil 51 } 52 53 func (p *lazyProc) Addr() uintptr { 54 err := p.Find() 55 if err != nil { 56 panic(err) 57 } 58 return p.addr 59 }