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