Source file 
src/syscall/dll_windows.go
     1  
     2  
     3  
     4  
     5  package syscall
     6  
     7  import (
     8  	"internal/syscall/windows/sysdll"
     9  	"sync"
    10  	"sync/atomic"
    11  	"unsafe"
    12  )
    13  
    14  
    15  type DLLError struct {
    16  	Err     error
    17  	ObjName string
    18  	Msg     string
    19  }
    20  
    21  func (e *DLLError) Error() string { return e.Msg }
    22  
    23  func (e *DLLError) Unwrap() error { return e.Err }
    24  
    25  
    26  
    27  
    28  func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
    29  
    30  
    31  func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
    32  
    33  
    34  func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
    35  
    36  
    37  func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
    38  
    39  
    40  func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)
    41  
    42  
    43  func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno)
    44  
    45  
    46  func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
    47  func loadlibrary(filename *uint16) (handle uintptr, err Errno)
    48  func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno)
    49  func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
    50  
    51  
    52  type DLL struct {
    53  	Name   string
    54  	Handle Handle
    55  }
    56  
    57  
    58  
    59  
    60  
    61  
    62  
    63  
    64  
    65  func LoadDLL(name string) (*DLL, error) {
    66  	namep, err := UTF16PtrFromString(name)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	var h uintptr
    71  	var e Errno
    72  	if sysdll.IsSystemDLL[name] {
    73  		h, e = loadsystemlibrary(namep)
    74  	} else {
    75  		h, e = loadlibrary(namep)
    76  	}
    77  	if e != 0 {
    78  		return nil, &DLLError{
    79  			Err:     e,
    80  			ObjName: name,
    81  			Msg:     "Failed to load " + name + ": " + e.Error(),
    82  		}
    83  	}
    84  	d := &DLL{
    85  		Name:   name,
    86  		Handle: Handle(h),
    87  	}
    88  	return d, nil
    89  }
    90  
    91  
    92  func MustLoadDLL(name string) *DLL {
    93  	d, e := LoadDLL(name)
    94  	if e != nil {
    95  		panic(e)
    96  	}
    97  	return d
    98  }
    99  
   100  
   101  
   102  func (d *DLL) FindProc(name string) (proc *Proc, err error) {
   103  	namep, err := BytePtrFromString(name)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	a, e := getprocaddress(uintptr(d.Handle), namep)
   108  	if e != 0 {
   109  		return nil, &DLLError{
   110  			Err:     e,
   111  			ObjName: name,
   112  			Msg:     "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
   113  		}
   114  	}
   115  	p := &Proc{
   116  		Dll:  d,
   117  		Name: name,
   118  		addr: a,
   119  	}
   120  	return p, nil
   121  }
   122  
   123  
   124  func (d *DLL) MustFindProc(name string) *Proc {
   125  	p, e := d.FindProc(name)
   126  	if e != nil {
   127  		panic(e)
   128  	}
   129  	return p
   130  }
   131  
   132  
   133  func (d *DLL) Release() (err error) {
   134  	return FreeLibrary(d.Handle)
   135  }
   136  
   137  
   138  type Proc struct {
   139  	Dll  *DLL
   140  	Name string
   141  	addr uintptr
   142  }
   143  
   144  
   145  
   146  func (p *Proc) Addr() uintptr {
   147  	return p.addr
   148  }
   149  
   150  
   151  
   152  
   153  
   154  
   155  
   156  
   157  
   158  
   159  
   160  
   161  
   162  
   163  
   164  
   165  
   166  func (p *Proc) Call(a ...uintptr) (uintptr, uintptr, error) {
   167  	return SyscallN(p.Addr(), a...)
   168  }
   169  
   170  
   171  
   172  
   173  
   174  
   175  
   176  
   177  
   178  
   179  
   180  type LazyDLL struct {
   181  	mu   sync.Mutex
   182  	dll  *DLL 
   183  	Name string
   184  }
   185  
   186  
   187  
   188  func (d *LazyDLL) Load() error {
   189  	
   190  	
   191  	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil {
   192  		d.mu.Lock()
   193  		defer d.mu.Unlock()
   194  		if d.dll == nil {
   195  			dll, e := LoadDLL(d.Name)
   196  			if e != nil {
   197  				return e
   198  			}
   199  			
   200  			
   201  			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
   202  		}
   203  	}
   204  	return nil
   205  }
   206  
   207  
   208  func (d *LazyDLL) mustLoad() {
   209  	e := d.Load()
   210  	if e != nil {
   211  		panic(e)
   212  	}
   213  }
   214  
   215  
   216  func (d *LazyDLL) Handle() uintptr {
   217  	d.mustLoad()
   218  	return uintptr(d.dll.Handle)
   219  }
   220  
   221  
   222  func (d *LazyDLL) NewProc(name string) *LazyProc {
   223  	return &LazyProc{l: d, Name: name}
   224  }
   225  
   226  
   227  func NewLazyDLL(name string) *LazyDLL {
   228  	return &LazyDLL{Name: name}
   229  }
   230  
   231  
   232  
   233  type LazyProc struct {
   234  	mu   sync.Mutex
   235  	Name string
   236  	l    *LazyDLL
   237  	proc *Proc
   238  }
   239  
   240  
   241  
   242  
   243  func (p *LazyProc) Find() error {
   244  	
   245  	
   246  	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
   247  		p.mu.Lock()
   248  		defer p.mu.Unlock()
   249  		if p.proc == nil {
   250  			e := p.l.Load()
   251  			if e != nil {
   252  				return e
   253  			}
   254  			proc, e := p.l.dll.FindProc(p.Name)
   255  			if e != nil {
   256  				return e
   257  			}
   258  			
   259  			
   260  			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
   261  		}
   262  	}
   263  	return nil
   264  }
   265  
   266  
   267  func (p *LazyProc) mustFind() {
   268  	e := p.Find()
   269  	if e != nil {
   270  		panic(e)
   271  	}
   272  }
   273  
   274  
   275  
   276  func (p *LazyProc) Addr() uintptr {
   277  	p.mustFind()
   278  	return p.proc.Addr()
   279  }
   280  
   281  
   282  
   283  
   284  
   285  func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
   286  	p.mustFind()
   287  	return p.proc.Call(a...)
   288  }
   289  
View as plain text