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