Source file
src/syscall/syscall_windows.go
1
2
3
4
5
6
7 package syscall
8
9 import (
10 errorspkg "errors"
11 "internal/itoa"
12 "internal/oserror"
13 "internal/race"
14 "internal/unsafeheader"
15 "runtime"
16 "sync"
17 "unicode/utf16"
18 "unsafe"
19 )
20
21 type Handle uintptr
22
23 const InvalidHandle = ^Handle(0)
24
25
26
27
28
29
30 func StringToUTF16(s string) []uint16 {
31 a, err := UTF16FromString(s)
32 if err != nil {
33 panic("syscall: string with NUL passed to StringToUTF16")
34 }
35 return a
36 }
37
38
39
40
41 func UTF16FromString(s string) ([]uint16, error) {
42 for i := 0; i < len(s); i++ {
43 if s[i] == 0 {
44 return nil, EINVAL
45 }
46 }
47 return utf16.Encode([]rune(s + "\x00")), nil
48 }
49
50
51
52 func UTF16ToString(s []uint16) string {
53 for i, v := range s {
54 if v == 0 {
55 s = s[0:i]
56 break
57 }
58 }
59 return string(utf16.Decode(s))
60 }
61
62
63
64 func utf16PtrToString(p *uint16) string {
65 if p == nil {
66 return ""
67 }
68
69 end := unsafe.Pointer(p)
70 n := 0
71 for *(*uint16)(end) != 0 {
72 end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
73 n++
74 }
75
76 var s []uint16
77 hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
78 hdr.Data = unsafe.Pointer(p)
79 hdr.Cap = n
80 hdr.Len = n
81
82 return string(utf16.Decode(s))
83 }
84
85
86
87
88
89
90
91 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
92
93
94
95
96 func UTF16PtrFromString(s string) (*uint16, error) {
97 a, err := UTF16FromString(s)
98 if err != nil {
99 return nil, err
100 }
101 return &a[0], nil
102 }
103
104
105
106
107
108
109
110
111 type Errno uintptr
112
113 func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) }
114
115
116
117
118
119 func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
120 return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
121 }
122
123 func (e Errno) Error() string {
124
125 idx := int(e - APPLICATION_ERROR)
126 if 0 <= idx && idx < len(errors) {
127 return errors[idx]
128 }
129
130 var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
131 b := make([]uint16, 300)
132 n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil)
133 if err != nil {
134 n, err = formatMessage(flags, 0, uint32(e), 0, b, nil)
135 if err != nil {
136 return "winapi error #" + itoa.Itoa(int(e))
137 }
138 }
139
140 for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
141 }
142 return string(utf16.Decode(b[:n]))
143 }
144
145 const _ERROR_BAD_NETPATH = Errno(53)
146
147 func (e Errno) Is(target error) bool {
148 switch target {
149 case oserror.ErrPermission:
150 return e == ERROR_ACCESS_DENIED
151 case oserror.ErrExist:
152 return e == ERROR_ALREADY_EXISTS ||
153 e == ERROR_DIR_NOT_EMPTY ||
154 e == ERROR_FILE_EXISTS
155 case oserror.ErrNotExist:
156 return e == ERROR_FILE_NOT_FOUND ||
157 e == _ERROR_BAD_NETPATH ||
158 e == ERROR_PATH_NOT_FOUND
159 }
160 return false
161 }
162
163 func (e Errno) Temporary() bool {
164 return e == EINTR || e == EMFILE || e.Timeout()
165 }
166
167 func (e Errno) Timeout() bool {
168 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
169 }
170
171
172 func compileCallback(fn any, cleanstack bool) uintptr
173
174
175
176
177
178
179
180 func NewCallback(fn any) uintptr {
181 return compileCallback(fn, true)
182 }
183
184
185
186
187
188
189
190 func NewCallbackCDecl(fn any) uintptr {
191 return compileCallback(fn, false)
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 func makeInheritSa() *SecurityAttributes {
302 var sa SecurityAttributes
303 sa.Length = uint32(unsafe.Sizeof(sa))
304 sa.InheritHandle = 1
305 return &sa
306 }
307
308 func Open(path string, mode int, perm uint32) (fd Handle, err error) {
309 if len(path) == 0 {
310 return InvalidHandle, ERROR_FILE_NOT_FOUND
311 }
312 pathp, err := UTF16PtrFromString(path)
313 if err != nil {
314 return InvalidHandle, err
315 }
316 var access uint32
317 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
318 case O_RDONLY:
319 access = GENERIC_READ
320 case O_WRONLY:
321 access = GENERIC_WRITE
322 case O_RDWR:
323 access = GENERIC_READ | GENERIC_WRITE
324 }
325 if mode&O_CREAT != 0 {
326 access |= GENERIC_WRITE
327 }
328 if mode&O_APPEND != 0 {
329 access &^= GENERIC_WRITE
330 access |= FILE_APPEND_DATA
331 }
332 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
333 var sa *SecurityAttributes
334 if mode&O_CLOEXEC == 0 {
335 sa = makeInheritSa()
336 }
337 var createmode uint32
338 switch {
339 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
340 createmode = CREATE_NEW
341 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
342 createmode = CREATE_ALWAYS
343 case mode&O_CREAT == O_CREAT:
344 createmode = OPEN_ALWAYS
345 case mode&O_TRUNC == O_TRUNC:
346 createmode = TRUNCATE_EXISTING
347 default:
348 createmode = OPEN_EXISTING
349 }
350 var attrs uint32 = FILE_ATTRIBUTE_NORMAL
351 if perm&S_IWRITE == 0 {
352 attrs = FILE_ATTRIBUTE_READONLY
353 if createmode == CREATE_ALWAYS {
354
355
356
357
358
359
360
361
362 h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
363 switch e {
364 case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND:
365
366
367
368 default:
369
370 return h, e
371 }
372 }
373 }
374 h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
375 return h, e
376 }
377
378 func Read(fd Handle, p []byte) (n int, err error) {
379 var done uint32
380 e := ReadFile(fd, p, &done, nil)
381 if e != nil {
382 if e == ERROR_BROKEN_PIPE {
383
384 return 0, nil
385 }
386 return 0, e
387 }
388 if race.Enabled {
389 if done > 0 {
390 race.WriteRange(unsafe.Pointer(&p[0]), int(done))
391 }
392 race.Acquire(unsafe.Pointer(&ioSync))
393 }
394 if msanenabled && done > 0 {
395 msanWrite(unsafe.Pointer(&p[0]), int(done))
396 }
397 if asanenabled && done > 0 {
398 asanWrite(unsafe.Pointer(&p[0]), int(done))
399 }
400 return int(done), nil
401 }
402
403 func Write(fd Handle, p []byte) (n int, err error) {
404 if race.Enabled {
405 race.ReleaseMerge(unsafe.Pointer(&ioSync))
406 }
407 var done uint32
408 e := WriteFile(fd, p, &done, nil)
409 if e != nil {
410 return 0, e
411 }
412 if race.Enabled && done > 0 {
413 race.ReadRange(unsafe.Pointer(&p[0]), int(done))
414 }
415 if msanenabled && done > 0 {
416 msanRead(unsafe.Pointer(&p[0]), int(done))
417 }
418 if asanenabled && done > 0 {
419 asanRead(unsafe.Pointer(&p[0]), int(done))
420 }
421 return int(done), nil
422 }
423
424 var ioSync int64
425
426 var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
427
428 const ptrSize = unsafe.Sizeof(uintptr(0))
429
430
431
432 func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
433 var e1 Errno
434 if unsafe.Sizeof(uintptr(0)) == 8 {
435 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
436 } else {
437
438 switch runtime.GOARCH {
439 default:
440 panic("unsupported 32-bit architecture")
441 case "386":
442
443
444 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
445 case "arm":
446
447
448 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence))
449 }
450 }
451 if e1 != 0 {
452 return errnoErr(e1)
453 }
454 return nil
455 }
456
457 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
458 var w uint32
459 switch whence {
460 case 0:
461 w = FILE_BEGIN
462 case 1:
463 w = FILE_CURRENT
464 case 2:
465 w = FILE_END
466 }
467
468 ft, _ := GetFileType(fd)
469 if ft == FILE_TYPE_PIPE {
470 return 0, ESPIPE
471 }
472 err = setFilePointerEx(fd, offset, &newoffset, w)
473 return
474 }
475
476 func Close(fd Handle) (err error) {
477 return CloseHandle(fd)
478 }
479
480 var (
481 Stdin = getStdHandle(STD_INPUT_HANDLE)
482 Stdout = getStdHandle(STD_OUTPUT_HANDLE)
483 Stderr = getStdHandle(STD_ERROR_HANDLE)
484 )
485
486 func getStdHandle(h int) (fd Handle) {
487 r, _ := GetStdHandle(h)
488 return r
489 }
490
491 const ImplementsGetwd = true
492
493 func Getwd() (wd string, err error) {
494 b := make([]uint16, 300)
495 n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
496 if e != nil {
497 return "", e
498 }
499 return string(utf16.Decode(b[0:n])), nil
500 }
501
502 func Chdir(path string) (err error) {
503 pathp, err := UTF16PtrFromString(path)
504 if err != nil {
505 return err
506 }
507 return SetCurrentDirectory(pathp)
508 }
509
510 func Mkdir(path string, mode uint32) (err error) {
511 pathp, err := UTF16PtrFromString(path)
512 if err != nil {
513 return err
514 }
515 return CreateDirectory(pathp, nil)
516 }
517
518 func Rmdir(path string) (err error) {
519 pathp, err := UTF16PtrFromString(path)
520 if err != nil {
521 return err
522 }
523 return RemoveDirectory(pathp)
524 }
525
526 func Unlink(path string) (err error) {
527 pathp, err := UTF16PtrFromString(path)
528 if err != nil {
529 return err
530 }
531 return DeleteFile(pathp)
532 }
533
534 func Rename(oldpath, newpath string) (err error) {
535 from, err := UTF16PtrFromString(oldpath)
536 if err != nil {
537 return err
538 }
539 to, err := UTF16PtrFromString(newpath)
540 if err != nil {
541 return err
542 }
543 return MoveFile(from, to)
544 }
545
546 func ComputerName() (name string, err error) {
547 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
548 b := make([]uint16, n)
549 e := GetComputerName(&b[0], &n)
550 if e != nil {
551 return "", e
552 }
553 return string(utf16.Decode(b[0:n])), nil
554 }
555
556 func Ftruncate(fd Handle, length int64) (err error) {
557 curoffset, e := Seek(fd, 0, 1)
558 if e != nil {
559 return e
560 }
561 defer Seek(fd, curoffset, 0)
562 _, e = Seek(fd, length, 0)
563 if e != nil {
564 return e
565 }
566 e = SetEndOfFile(fd)
567 if e != nil {
568 return e
569 }
570 return nil
571 }
572
573 func Gettimeofday(tv *Timeval) (err error) {
574 var ft Filetime
575 GetSystemTimeAsFileTime(&ft)
576 *tv = NsecToTimeval(ft.Nanoseconds())
577 return nil
578 }
579
580 func Pipe(p []Handle) (err error) {
581 if len(p) != 2 {
582 return EINVAL
583 }
584 var r, w Handle
585 e := CreatePipe(&r, &w, makeInheritSa(), 0)
586 if e != nil {
587 return e
588 }
589 p[0] = r
590 p[1] = w
591 return nil
592 }
593
594 func Utimes(path string, tv []Timeval) (err error) {
595 if len(tv) != 2 {
596 return EINVAL
597 }
598 pathp, e := UTF16PtrFromString(path)
599 if e != nil {
600 return e
601 }
602 h, e := CreateFile(pathp,
603 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
604 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
605 if e != nil {
606 return e
607 }
608 defer Close(h)
609 a := NsecToFiletime(tv[0].Nanoseconds())
610 w := NsecToFiletime(tv[1].Nanoseconds())
611 return SetFileTime(h, nil, &a, &w)
612 }
613
614 func UtimesNano(path string, ts []Timespec) (err error) {
615 if len(ts) != 2 {
616 return EINVAL
617 }
618 pathp, e := UTF16PtrFromString(path)
619 if e != nil {
620 return e
621 }
622 h, e := CreateFile(pathp,
623 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
624 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
625 if e != nil {
626 return e
627 }
628 defer Close(h)
629 a := NsecToFiletime(TimespecToNsec(ts[0]))
630 w := NsecToFiletime(TimespecToNsec(ts[1]))
631 return SetFileTime(h, nil, &a, &w)
632 }
633
634 func Fsync(fd Handle) (err error) {
635 return FlushFileBuffers(fd)
636 }
637
638 func Chmod(path string, mode uint32) (err error) {
639 p, e := UTF16PtrFromString(path)
640 if e != nil {
641 return e
642 }
643 attrs, e := GetFileAttributes(p)
644 if e != nil {
645 return e
646 }
647 if mode&S_IWRITE != 0 {
648 attrs &^= FILE_ATTRIBUTE_READONLY
649 } else {
650 attrs |= FILE_ATTRIBUTE_READONLY
651 }
652 return SetFileAttributes(p, attrs)
653 }
654
655 func LoadCancelIoEx() error {
656 return procCancelIoEx.Find()
657 }
658
659 func LoadSetFileCompletionNotificationModes() error {
660 return procSetFileCompletionNotificationModes.Find()
661 }
662
663
664
665 const socket_error = uintptr(^uint32(0))
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702 var SocketDisableIPv6 bool
703
704 type RawSockaddrInet4 struct {
705 Family uint16
706 Port uint16
707 Addr [4]byte
708 Zero [8]uint8
709 }
710
711 type RawSockaddrInet6 struct {
712 Family uint16
713 Port uint16
714 Flowinfo uint32
715 Addr [16]byte
716 Scope_id uint32
717 }
718
719 type RawSockaddr struct {
720 Family uint16
721 Data [14]int8
722 }
723
724 type RawSockaddrAny struct {
725 Addr RawSockaddr
726 Pad [100]int8
727 }
728
729 type Sockaddr interface {
730 sockaddr() (ptr unsafe.Pointer, len int32, err error)
731 }
732
733 type SockaddrInet4 struct {
734 Port int
735 Addr [4]byte
736 raw RawSockaddrInet4
737 }
738
739 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
740 if sa.Port < 0 || sa.Port > 0xFFFF {
741 return nil, 0, EINVAL
742 }
743 sa.raw.Family = AF_INET
744 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
745 p[0] = byte(sa.Port >> 8)
746 p[1] = byte(sa.Port)
747 sa.raw.Addr = sa.Addr
748 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
749 }
750
751 type SockaddrInet6 struct {
752 Port int
753 ZoneId uint32
754 Addr [16]byte
755 raw RawSockaddrInet6
756 }
757
758 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
759 if sa.Port < 0 || sa.Port > 0xFFFF {
760 return nil, 0, EINVAL
761 }
762 sa.raw.Family = AF_INET6
763 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
764 p[0] = byte(sa.Port >> 8)
765 p[1] = byte(sa.Port)
766 sa.raw.Scope_id = sa.ZoneId
767 sa.raw.Addr = sa.Addr
768 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
769 }
770
771 type RawSockaddrUnix struct {
772 Family uint16
773 Path [UNIX_PATH_MAX]int8
774 }
775
776 type SockaddrUnix struct {
777 Name string
778 raw RawSockaddrUnix
779 }
780
781 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
782 name := sa.Name
783 n := len(name)
784 if n > len(sa.raw.Path) {
785 return nil, 0, EINVAL
786 }
787 if n == len(sa.raw.Path) && name[0] != '@' {
788 return nil, 0, EINVAL
789 }
790 sa.raw.Family = AF_UNIX
791 for i := 0; i < n; i++ {
792 sa.raw.Path[i] = int8(name[i])
793 }
794
795 sl := int32(2)
796 if n > 0 {
797 sl += int32(n) + 1
798 }
799 if sa.raw.Path[0] == '@' {
800 sa.raw.Path[0] = 0
801
802 sl--
803 }
804
805 return unsafe.Pointer(&sa.raw), sl, nil
806 }
807
808 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
809 switch rsa.Addr.Family {
810 case AF_UNIX:
811 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
812 sa := new(SockaddrUnix)
813 if pp.Path[0] == 0 {
814
815
816
817
818
819 pp.Path[0] = '@'
820 }
821
822
823
824
825
826
827 n := 0
828 for n < len(pp.Path) && pp.Path[n] != 0 {
829 n++
830 }
831 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n:n]
832 sa.Name = string(bytes)
833 return sa, nil
834
835 case AF_INET:
836 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
837 sa := new(SockaddrInet4)
838 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
839 sa.Port = int(p[0])<<8 + int(p[1])
840 sa.Addr = pp.Addr
841 return sa, nil
842
843 case AF_INET6:
844 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
845 sa := new(SockaddrInet6)
846 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
847 sa.Port = int(p[0])<<8 + int(p[1])
848 sa.ZoneId = pp.Scope_id
849 sa.Addr = pp.Addr
850 return sa, nil
851 }
852 return nil, EAFNOSUPPORT
853 }
854
855 func Socket(domain, typ, proto int) (fd Handle, err error) {
856 if domain == AF_INET6 && SocketDisableIPv6 {
857 return InvalidHandle, EAFNOSUPPORT
858 }
859 return socket(int32(domain), int32(typ), int32(proto))
860 }
861
862 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
863 v := int32(value)
864 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
865 }
866
867 func Bind(fd Handle, sa Sockaddr) (err error) {
868 ptr, n, err := sa.sockaddr()
869 if err != nil {
870 return err
871 }
872 return bind(fd, ptr, n)
873 }
874
875 func Connect(fd Handle, sa Sockaddr) (err error) {
876 ptr, n, err := sa.sockaddr()
877 if err != nil {
878 return err
879 }
880 return connect(fd, ptr, n)
881 }
882
883 func Getsockname(fd Handle) (sa Sockaddr, err error) {
884 var rsa RawSockaddrAny
885 l := int32(unsafe.Sizeof(rsa))
886 if err = getsockname(fd, &rsa, &l); err != nil {
887 return
888 }
889 return rsa.Sockaddr()
890 }
891
892 func Getpeername(fd Handle) (sa Sockaddr, err error) {
893 var rsa RawSockaddrAny
894 l := int32(unsafe.Sizeof(rsa))
895 if err = getpeername(fd, &rsa, &l); err != nil {
896 return
897 }
898 return rsa.Sockaddr()
899 }
900
901 func Listen(s Handle, n int) (err error) {
902 return listen(s, int32(n))
903 }
904
905 func Shutdown(fd Handle, how int) (err error) {
906 return shutdown(fd, int32(how))
907 }
908
909 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
910 rsa, len, err := to.sockaddr()
911 if err != nil {
912 return err
913 }
914 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
915 if r1 == socket_error {
916 if e1 != 0 {
917 err = errnoErr(e1)
918 } else {
919 err = EINVAL
920 }
921 }
922 return err
923 }
924
925 func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
926 rsa, len, err := to.sockaddr()
927 if err != nil {
928 return err
929 }
930 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
931 if r1 == socket_error {
932 if e1 != 0 {
933 err = errnoErr(e1)
934 } else {
935 err = EINVAL
936 }
937 }
938 return err
939 }
940
941 func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
942 rsa, len, err := to.sockaddr()
943 if err != nil {
944 return err
945 }
946 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
947 if r1 == socket_error {
948 if e1 != 0 {
949 err = errnoErr(e1)
950 } else {
951 err = EINVAL
952 }
953 }
954 return err
955 }
956
957 func LoadGetAddrInfo() error {
958 return procGetAddrInfoW.Find()
959 }
960
961 var connectExFunc struct {
962 once sync.Once
963 addr uintptr
964 err error
965 }
966
967 func LoadConnectEx() error {
968 connectExFunc.once.Do(func() {
969 var s Handle
970 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
971 if connectExFunc.err != nil {
972 return
973 }
974 defer CloseHandle(s)
975 var n uint32
976 connectExFunc.err = WSAIoctl(s,
977 SIO_GET_EXTENSION_FUNCTION_POINTER,
978 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
979 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
980 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
981 uint32(unsafe.Sizeof(connectExFunc.addr)),
982 &n, nil, 0)
983 })
984 return connectExFunc.err
985 }
986
987 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
988 r1, _, e1 := Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0)
989 if r1 == 0 {
990 if e1 != 0 {
991 err = error(e1)
992 } else {
993 err = EINVAL
994 }
995 }
996 return
997 }
998
999 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
1000 err := LoadConnectEx()
1001 if err != nil {
1002 return errorspkg.New("failed to find ConnectEx: " + err.Error())
1003 }
1004 ptr, n, err := sa.sockaddr()
1005 if err != nil {
1006 return err
1007 }
1008 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
1009 }
1010
1011
1012 type Rusage struct {
1013 CreationTime Filetime
1014 ExitTime Filetime
1015 KernelTime Filetime
1016 UserTime Filetime
1017 }
1018
1019 type WaitStatus struct {
1020 ExitCode uint32
1021 }
1022
1023 func (w WaitStatus) Exited() bool { return true }
1024
1025 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
1026
1027 func (w WaitStatus) Signal() Signal { return -1 }
1028
1029 func (w WaitStatus) CoreDump() bool { return false }
1030
1031 func (w WaitStatus) Stopped() bool { return false }
1032
1033 func (w WaitStatus) Continued() bool { return false }
1034
1035 func (w WaitStatus) StopSignal() Signal { return -1 }
1036
1037 func (w WaitStatus) Signaled() bool { return false }
1038
1039 func (w WaitStatus) TrapCause() int { return -1 }
1040
1041
1042
1043 type Timespec struct {
1044 Sec int64
1045 Nsec int64
1046 }
1047
1048 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1049
1050 func NsecToTimespec(nsec int64) (ts Timespec) {
1051 ts.Sec = nsec / 1e9
1052 ts.Nsec = nsec % 1e9
1053 return
1054 }
1055
1056
1057
1058 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1059 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1060 return 0, nil, EWINDOWS
1061 }
1062 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS }
1063 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1064
1065
1066
1067
1068
1069
1070
1071
1072 type Linger struct {
1073 Onoff int32
1074 Linger int32
1075 }
1076
1077 type sysLinger struct {
1078 Onoff uint16
1079 Linger uint16
1080 }
1081
1082 type IPMreq struct {
1083 Multiaddr [4]byte
1084 Interface [4]byte
1085 }
1086
1087 type IPv6Mreq struct {
1088 Multiaddr [16]byte
1089 Interface uint32
1090 }
1091
1092 func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS }
1093
1094 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1095 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1096 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1097 }
1098
1099 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1100 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1101 }
1102 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1103 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1104 }
1105 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
1106
1107 func Getpid() (pid int) { return int(getCurrentProcessId()) }
1108
1109 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1110
1111
1112
1113
1114
1115
1116
1117
1118 var data1 win32finddata1
1119 handle, err = findFirstFile1(name, &data1)
1120 if err == nil {
1121 copyFindData(data, &data1)
1122 }
1123 return
1124 }
1125
1126 func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1127 var data1 win32finddata1
1128 err = findNextFile1(handle, &data1)
1129 if err == nil {
1130 copyFindData(data, &data1)
1131 }
1132 return
1133 }
1134
1135 func getProcessEntry(pid int) (*ProcessEntry32, error) {
1136 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1137 if err != nil {
1138 return nil, err
1139 }
1140 defer CloseHandle(snapshot)
1141 var procEntry ProcessEntry32
1142 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1143 if err = Process32First(snapshot, &procEntry); err != nil {
1144 return nil, err
1145 }
1146 for {
1147 if procEntry.ProcessID == uint32(pid) {
1148 return &procEntry, nil
1149 }
1150 err = Process32Next(snapshot, &procEntry)
1151 if err != nil {
1152 return nil, err
1153 }
1154 }
1155 }
1156
1157 func Getppid() (ppid int) {
1158 pe, err := getProcessEntry(Getpid())
1159 if err != nil {
1160 return -1
1161 }
1162 return int(pe.ParentProcessID)
1163 }
1164
1165
1166 func Fchdir(fd Handle) (err error) { return EWINDOWS }
1167 func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1168 func Symlink(path, link string) (err error) { return EWINDOWS }
1169
1170 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
1171 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
1172 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1173 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS }
1174
1175 func Getuid() (uid int) { return -1 }
1176 func Geteuid() (euid int) { return -1 }
1177 func Getgid() (gid int) { return -1 }
1178 func Getegid() (egid int) { return -1 }
1179 func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1180
1181 type Signal int
1182
1183 func (s Signal) Signal() {}
1184
1185 func (s Signal) String() string {
1186 if 0 <= s && int(s) < len(signals) {
1187 str := signals[s]
1188 if str != "" {
1189 return str
1190 }
1191 }
1192 return "signal " + itoa.Itoa(int(s))
1193 }
1194
1195 func LoadCreateSymbolicLink() error {
1196 return procCreateSymbolicLinkW.Find()
1197 }
1198
1199
1200 func Readlink(path string, buf []byte) (n int, err error) {
1201 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1202 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1203 if err != nil {
1204 return -1, err
1205 }
1206 defer CloseHandle(fd)
1207
1208 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1209 var bytesReturned uint32
1210 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1211 if err != nil {
1212 return -1, err
1213 }
1214
1215 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1216 var s string
1217 switch rdb.ReparseTag {
1218 case IO_REPARSE_TAG_SYMLINK:
1219 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1220 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1221 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1222 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1223 if len(s) >= 4 && s[:4] == `\??\` {
1224 s = s[4:]
1225 switch {
1226 case len(s) >= 2 && s[1] == ':':
1227
1228 case len(s) >= 4 && s[:4] == `UNC\`:
1229 s = `\\` + s[4:]
1230 default:
1231
1232 }
1233 } else {
1234
1235 }
1236 }
1237 case _IO_REPARSE_TAG_MOUNT_POINT:
1238 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1239 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1240 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1241 if len(s) >= 4 && s[:4] == `\??\` {
1242 s = s[4:]
1243 } else {
1244
1245 }
1246 default:
1247
1248
1249 return -1, ENOENT
1250 }
1251 n = copy(buf, []byte(s))
1252
1253 return n, nil
1254 }
1255
1256
1257 func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1258 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1259 }
1260
1261
1262 func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1263 var ukey uintptr
1264 var pukey *uintptr
1265 if key != nil {
1266 ukey = uintptr(*key)
1267 pukey = &ukey
1268 }
1269 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1270 if key != nil {
1271 *key = uint32(ukey)
1272 if uintptr(*key) != ukey && err == nil {
1273 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1274 }
1275 }
1276 return err
1277 }
1278
1279
1280 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1281 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1282 }
1283
1284
1285
1286
1287 func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) {
1288 var size uintptr
1289 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1290 if err != ERROR_INSUFFICIENT_BUFFER {
1291 if err == nil {
1292 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1293 }
1294 return nil, err
1295 }
1296
1297 al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
1298 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
1299 if err != nil {
1300 return nil, err
1301 }
1302 return al, nil
1303 }
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329 func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1330 return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1331 }
1332
View as plain text