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