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