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
16
17
18 var (
19 __LoadLibraryExW unsafe.Pointer
20 __GetProcAddress unsafe.Pointer
21 )
22
23
24 type DLLError struct {
25 Err error
26 ObjName string
27 Msg string
28 }
29
30 func (e *DLLError) Error() string { return e.Msg }
31
32 func (e *DLLError) Unwrap() error { return e.Err }
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
49 return syscalln(trap, nargs, a1, a2, a3)
50 }
51
52
53
54
55
56 func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
57 return syscalln(trap, nargs, a1, a2, a3, a4, a5, a6)
58 }
59
60
61
62
63
64 func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) {
65 return syscalln(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9)
66 }
67
68
69
70
71
72 func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno) {
73 return syscalln(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
74 }
75
76
77
78
79
80 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) {
81 return syscalln(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
82 }
83
84
85
86
87
88 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) {
89 return syscalln(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18)
90 }
91
92
93
94
95
96
97
98 func SyscallN(p uintptr, args ...uintptr) (r1, r2 uintptr, err Errno) {
99 return syscalln(p, uintptr(len(args)), args...)
100 }
101
102
103
104
105 func syscalln(fn, n uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
106
107
108
109
110
111
112
113 func loadlibrary(filename *uint16) (uintptr, Errno) {
114 handle, _, err := SyscallN(uintptr(__LoadLibraryExW), uintptr(unsafe.Pointer(filename)), 0, 0)
115 if handle != 0 {
116 err = 0
117 }
118 return handle, err
119 }
120
121
122 func loadsystemlibrary(filename *uint16) (uintptr, Errno) {
123 const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
124 handle, _, err := SyscallN(uintptr(__LoadLibraryExW), uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
125 if handle != 0 {
126 err = 0
127 }
128 return handle, err
129 }
130
131
132 func getprocaddress(handle uintptr, procname *uint8) (uintptr, Errno) {
133 proc, _, err := SyscallN(uintptr(__GetProcAddress), handle, uintptr(unsafe.Pointer(procname)))
134 if proc != 0 {
135 err = 0
136 }
137 return proc, err
138 }
139
140
141 type DLL struct {
142 Name string
143 Handle Handle
144 }
145
146
147
148
149
150
151
152
153
154 func LoadDLL(name string) (*DLL, error) {
155 namep, err := UTF16PtrFromString(name)
156 if err != nil {
157 return nil, err
158 }
159 var h uintptr
160 var e Errno
161 if sysdll.IsSystemDLL[name] {
162 h, e = loadsystemlibrary(namep)
163 } else {
164 h, e = loadlibrary(namep)
165 }
166 if e != 0 {
167 return nil, &DLLError{
168 Err: e,
169 ObjName: name,
170 Msg: "Failed to load " + name + ": " + e.Error(),
171 }
172 }
173 d := &DLL{
174 Name: name,
175 Handle: Handle(h),
176 }
177 return d, nil
178 }
179
180
181 func MustLoadDLL(name string) *DLL {
182 d, e := LoadDLL(name)
183 if e != nil {
184 panic(e)
185 }
186 return d
187 }
188
189
190
191 func (d *DLL) FindProc(name string) (proc *Proc, err error) {
192 namep, err := BytePtrFromString(name)
193 if err != nil {
194 return nil, err
195 }
196 a, e := getprocaddress(uintptr(d.Handle), namep)
197 if e != 0 {
198 return nil, &DLLError{
199 Err: e,
200 ObjName: name,
201 Msg: "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
202 }
203 }
204 p := &Proc{
205 Dll: d,
206 Name: name,
207 addr: a,
208 }
209 return p, nil
210 }
211
212
213 func (d *DLL) MustFindProc(name string) *Proc {
214 p, e := d.FindProc(name)
215 if e != nil {
216 panic(e)
217 }
218 return p
219 }
220
221
222 func (d *DLL) Release() (err error) {
223 return FreeLibrary(d.Handle)
224 }
225
226
227 type Proc struct {
228 Dll *DLL
229 Name string
230 addr uintptr
231 }
232
233
234
235 func (p *Proc) Addr() uintptr {
236 return p.addr
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 func (p *Proc) Call(a ...uintptr) (uintptr, uintptr, error) {
256 return SyscallN(p.Addr(), a...)
257 }
258
259
260
261
262
263
264
265
266
267
268
269 type LazyDLL struct {
270 mu sync.Mutex
271 dll *DLL
272 Name string
273 }
274
275
276
277 func (d *LazyDLL) Load() error {
278
279
280 if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil {
281 d.mu.Lock()
282 defer d.mu.Unlock()
283 if d.dll == nil {
284 dll, e := LoadDLL(d.Name)
285 if e != nil {
286 return e
287 }
288
289
290 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
291 }
292 }
293 return nil
294 }
295
296
297 func (d *LazyDLL) mustLoad() {
298 e := d.Load()
299 if e != nil {
300 panic(e)
301 }
302 }
303
304
305 func (d *LazyDLL) Handle() uintptr {
306 d.mustLoad()
307 return uintptr(d.dll.Handle)
308 }
309
310
311 func (d *LazyDLL) NewProc(name string) *LazyProc {
312 return &LazyProc{l: d, Name: name}
313 }
314
315
316 func NewLazyDLL(name string) *LazyDLL {
317 return &LazyDLL{Name: name}
318 }
319
320
321
322 type LazyProc struct {
323 mu sync.Mutex
324 Name string
325 l *LazyDLL
326 proc *Proc
327 }
328
329
330
331
332 func (p *LazyProc) Find() error {
333
334
335 if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
336 p.mu.Lock()
337 defer p.mu.Unlock()
338 if p.proc == nil {
339 e := p.l.Load()
340 if e != nil {
341 return e
342 }
343 proc, e := p.l.dll.FindProc(p.Name)
344 if e != nil {
345 return e
346 }
347
348
349 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
350 }
351 }
352 return nil
353 }
354
355
356 func (p *LazyProc) mustFind() {
357 e := p.Find()
358 if e != nil {
359 panic(e)
360 }
361 }
362
363
364
365 func (p *LazyProc) Addr() uintptr {
366 p.mustFind()
367 return p.proc.Addr()
368 }
369
370
371
372
373
374 func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
375 p.mustFind()
376 return p.proc.Call(a...)
377 }
378
View as plain text