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 func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
46 func loadlibrary(filename *uint16) (handle uintptr, err Errno)
47 func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno)
48 func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
49
50
51 type DLL struct {
52 Name string
53 Handle Handle
54 }
55
56
57
58
59
60
61
62
63
64 func LoadDLL(name string) (*DLL, error) {
65 namep, err := UTF16PtrFromString(name)
66 if err != nil {
67 return nil, err
68 }
69 var h uintptr
70 var e Errno
71 if sysdll.IsSystemDLL[name] {
72 h, e = loadsystemlibrary(namep)
73 } else {
74 h, e = loadlibrary(namep)
75 }
76 if e != 0 {
77 return nil, &DLLError{
78 Err: e,
79 ObjName: name,
80 Msg: "Failed to load " + name + ": " + e.Error(),
81 }
82 }
83 d := &DLL{
84 Name: name,
85 Handle: Handle(h),
86 }
87 return d, nil
88 }
89
90
91 func MustLoadDLL(name string) *DLL {
92 d, e := LoadDLL(name)
93 if e != nil {
94 panic(e)
95 }
96 return d
97 }
98
99
100
101 func (d *DLL) FindProc(name string) (proc *Proc, err error) {
102 namep, err := BytePtrFromString(name)
103 if err != nil {
104 return nil, err
105 }
106 a, e := getprocaddress(uintptr(d.Handle), namep)
107 if e != 0 {
108 return nil, &DLLError{
109 Err: e,
110 ObjName: name,
111 Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
112 }
113 }
114 p := &Proc{
115 Dll: d,
116 Name: name,
117 addr: a,
118 }
119 return p, nil
120 }
121
122
123 func (d *DLL) MustFindProc(name string) *Proc {
124 p, e := d.FindProc(name)
125 if e != nil {
126 panic(e)
127 }
128 return p
129 }
130
131
132 func (d *DLL) Release() (err error) {
133 return FreeLibrary(d.Handle)
134 }
135
136
137 type Proc struct {
138 Dll *DLL
139 Name string
140 addr uintptr
141 }
142
143
144
145 func (p *Proc) Addr() uintptr {
146 return p.addr
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 func (p *Proc) Call(a ...uintptr) (uintptr, uintptr, error) {
166 return SyscallN(p.Addr(), a...)
167 }
168
169
170
171
172
173
174
175
176
177
178
179 type LazyDLL struct {
180 mu sync.Mutex
181 dll *DLL
182 Name string
183 }
184
185
186
187 func (d *LazyDLL) Load() error {
188
189
190 if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil {
191 d.mu.Lock()
192 defer d.mu.Unlock()
193 if d.dll == nil {
194 dll, e := LoadDLL(d.Name)
195 if e != nil {
196 return e
197 }
198
199
200 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
201 }
202 }
203 return nil
204 }
205
206
207 func (d *LazyDLL) mustLoad() {
208 e := d.Load()
209 if e != nil {
210 panic(e)
211 }
212 }
213
214
215 func (d *LazyDLL) Handle() uintptr {
216 d.mustLoad()
217 return uintptr(d.dll.Handle)
218 }
219
220
221 func (d *LazyDLL) NewProc(name string) *LazyProc {
222 return &LazyProc{l: d, Name: name}
223 }
224
225
226 func NewLazyDLL(name string) *LazyDLL {
227 return &LazyDLL{Name: name}
228 }
229
230
231
232 type LazyProc struct {
233 mu sync.Mutex
234 Name string
235 l *LazyDLL
236 proc *Proc
237 }
238
239
240
241
242 func (p *LazyProc) Find() error {
243
244
245 if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
246 p.mu.Lock()
247 defer p.mu.Unlock()
248 if p.proc == nil {
249 e := p.l.Load()
250 if e != nil {
251 return e
252 }
253 proc, e := p.l.dll.FindProc(p.Name)
254 if e != nil {
255 return e
256 }
257
258
259 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
260 }
261 }
262 return nil
263 }
264
265
266 func (p *LazyProc) mustFind() {
267 e := p.Find()
268 if e != nil {
269 panic(e)
270 }
271 }
272
273
274
275 func (p *LazyProc) Addr() uintptr {
276 p.mustFind()
277 return p.proc.Addr()
278 }
279
280
281
282
283
284 func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
285 p.mustFind()
286 return p.proc.Call(a...)
287 }
288
View as plain text