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