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