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 var access uint32
374 switch flag & (O_RDONLY | O_WRONLY | O_RDWR) {
375 case O_RDONLY:
376 access = GENERIC_READ
377 case O_WRONLY:
378 access = GENERIC_WRITE
379 case O_RDWR:
380 access = GENERIC_READ | GENERIC_WRITE
381 }
382 if flag&O_CREAT != 0 {
383 access |= GENERIC_WRITE
384 }
385 if flag&O_APPEND != 0 {
386
387
388
389 if flag&O_TRUNC == 0 {
390 access &^= GENERIC_WRITE
391 }
392
393 access |= FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | _FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE
394 }
395 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
396 var sa *SecurityAttributes
397 if flag&O_CLOEXEC == 0 {
398 sa = makeInheritSa()
399 }
400
401
402
403
404
405 var createmode uint32
406 switch {
407 case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
408 createmode = CREATE_NEW
409 case flag&O_CREAT == O_CREAT:
410 createmode = OPEN_ALWAYS
411 default:
412 createmode = OPEN_EXISTING
413 }
414 var attrs uint32 = FILE_ATTRIBUTE_NORMAL
415 if perm&S_IWRITE == 0 {
416 attrs = FILE_ATTRIBUTE_READONLY
417 }
418 if flag&O_WRONLY == 0 && flag&O_RDWR == 0 {
419
420
421
422 attrs |= FILE_FLAG_BACKUP_SEMANTICS
423 }
424 if flag&O_SYNC != 0 {
425 const _FILE_FLAG_WRITE_THROUGH = 0x80000000
426 attrs |= _FILE_FLAG_WRITE_THROUGH
427 }
428 h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
429 if h == InvalidHandle {
430 if err == ERROR_ACCESS_DENIED && (flag&O_WRONLY != 0 || flag&O_RDWR != 0) {
431
432 fa, e1 := GetFileAttributes(namep)
433 if e1 == nil && fa&FILE_ATTRIBUTE_DIRECTORY != 0 {
434 err = EISDIR
435 }
436 }
437 return h, err
438 }
439
440 if flag&O_TRUNC == O_TRUNC &&
441 (createmode == OPEN_EXISTING || (createmode == OPEN_ALWAYS && err == ERROR_ALREADY_EXISTS)) {
442 err = Ftruncate(h, 0)
443 if err != nil {
444 CloseHandle(h)
445 return InvalidHandle, err
446 }
447 }
448 return h, nil
449 }
450
451 func Read(fd Handle, p []byte) (n int, err error) {
452 var done uint32
453 e := ReadFile(fd, p, &done, nil)
454 if e != nil {
455 if e == ERROR_BROKEN_PIPE {
456
457 return 0, nil
458 }
459 return 0, e
460 }
461 return int(done), nil
462 }
463
464 func Write(fd Handle, p []byte) (n int, err error) {
465 var done uint32
466 e := WriteFile(fd, p, &done, nil)
467 if e != nil {
468 return 0, e
469 }
470 return int(done), nil
471 }
472
473 func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
474 err := readFile(fd, p, done, overlapped)
475 if race.Enabled {
476 if *done > 0 {
477 race.WriteRange(unsafe.Pointer(&p[0]), int(*done))
478 }
479 race.Acquire(unsafe.Pointer(&ioSync))
480 }
481 if msan.Enabled && *done > 0 {
482 msan.Write(unsafe.Pointer(&p[0]), uintptr(*done))
483 }
484 if asan.Enabled && *done > 0 {
485 asan.Write(unsafe.Pointer(&p[0]), uintptr(*done))
486 }
487 return err
488 }
489
490 func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
491 if race.Enabled {
492 race.ReleaseMerge(unsafe.Pointer(&ioSync))
493 }
494 err := writeFile(fd, p, done, overlapped)
495 if race.Enabled && *done > 0 {
496 race.ReadRange(unsafe.Pointer(&p[0]), int(*done))
497 }
498 if msan.Enabled && *done > 0 {
499 msan.Read(unsafe.Pointer(&p[0]), uintptr(*done))
500 }
501 if asan.Enabled && *done > 0 {
502 asan.Read(unsafe.Pointer(&p[0]), uintptr(*done))
503 }
504 return err
505 }
506
507 var ioSync int64
508
509 var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
510
511 const ptrSize = unsafe.Sizeof(uintptr(0))
512
513
514
515 func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
516 var e1 Errno
517 if unsafe.Sizeof(uintptr(0)) == 8 {
518 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
519 } else {
520
521 switch runtime.GOARCH {
522 default:
523 panic("unsupported 32-bit architecture")
524 case "386":
525
526 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
527 case "arm":
528
529
530 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence))
531 }
532 }
533 if e1 != 0 {
534 return errnoErr(e1)
535 }
536 return nil
537 }
538
539 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
540 var w uint32
541 switch whence {
542 case 0:
543 w = FILE_BEGIN
544 case 1:
545 w = FILE_CURRENT
546 case 2:
547 w = FILE_END
548 }
549 err = setFilePointerEx(fd, offset, &newoffset, w)
550 return
551 }
552
553 func Close(fd Handle) (err error) {
554 return CloseHandle(fd)
555 }
556
557 var (
558 Stdin = getStdHandle(STD_INPUT_HANDLE)
559 Stdout = getStdHandle(STD_OUTPUT_HANDLE)
560 Stderr = getStdHandle(STD_ERROR_HANDLE)
561 )
562
563 func getStdHandle(h int) (fd Handle) {
564 r, _ := GetStdHandle(h)
565 return r
566 }
567
568 const ImplementsGetwd = true
569
570 func Getwd() (wd string, err error) {
571 b := make([]uint16, 300)
572
573
574
575
576
577 for {
578 n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
579 if e != nil {
580 return "", e
581 }
582 if int(n) <= len(b) {
583 return UTF16ToString(b[:n]), nil
584 }
585 b = make([]uint16, n)
586 }
587 }
588
589 func Chdir(path string) (err error) {
590 pathp, err := UTF16PtrFromString(path)
591 if err != nil {
592 return err
593 }
594 return SetCurrentDirectory(pathp)
595 }
596
597 func Mkdir(path string, mode uint32) (err error) {
598 pathp, err := UTF16PtrFromString(path)
599 if err != nil {
600 return err
601 }
602 return CreateDirectory(pathp, nil)
603 }
604
605 func Rmdir(path string) (err error) {
606 pathp, err := UTF16PtrFromString(path)
607 if err != nil {
608 return err
609 }
610 return RemoveDirectory(pathp)
611 }
612
613 func Unlink(path string) (err error) {
614 pathp, err := UTF16PtrFromString(path)
615 if err != nil {
616 return err
617 }
618 return DeleteFile(pathp)
619 }
620
621 func Rename(oldpath, newpath string) (err error) {
622 from, err := UTF16PtrFromString(oldpath)
623 if err != nil {
624 return err
625 }
626 to, err := UTF16PtrFromString(newpath)
627 if err != nil {
628 return err
629 }
630 return MoveFile(from, to)
631 }
632
633 func ComputerName() (name string, err error) {
634 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
635 b := make([]uint16, n)
636 e := GetComputerName(&b[0], &n)
637 if e != nil {
638 return "", e
639 }
640 return UTF16ToString(b[:n]), nil
641 }
642
643 func Ftruncate(fd Handle, length int64) (err error) {
644 type _FILE_END_OF_FILE_INFO struct {
645 EndOfFile int64
646 }
647 const FileEndOfFileInfo = 6
648 var info _FILE_END_OF_FILE_INFO
649 info.EndOfFile = length
650 return setFileInformationByHandle(fd, FileEndOfFileInfo, unsafe.Pointer(&info), uint32(unsafe.Sizeof(info)))
651 }
652
653 func Gettimeofday(tv *Timeval) (err error) {
654 var ft Filetime
655 GetSystemTimeAsFileTime(&ft)
656 *tv = NsecToTimeval(ft.Nanoseconds())
657 return nil
658 }
659
660 func Pipe(p []Handle) (err error) {
661 if len(p) != 2 {
662 return EINVAL
663 }
664 var r, w Handle
665 e := CreatePipe(&r, &w, makeInheritSa(), 0)
666 if e != nil {
667 return e
668 }
669 p[0] = r
670 p[1] = w
671 return nil
672 }
673
674 func Utimes(path string, tv []Timeval) (err error) {
675 if len(tv) != 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 tv[0].Nanoseconds() != 0 {
692 a = NsecToFiletime(tv[0].Nanoseconds())
693 }
694 if tv[0].Nanoseconds() != 0 {
695 w = NsecToFiletime(tv[1].Nanoseconds())
696 }
697 return SetFileTime(h, nil, &a, &w)
698 }
699
700
701 const _UTIME_OMIT = -1
702
703 func UtimesNano(path string, ts []Timespec) (err error) {
704 if len(ts) != 2 {
705 return EINVAL
706 }
707 pathp, e := UTF16PtrFromString(path)
708 if e != nil {
709 return e
710 }
711 h, e := CreateFile(pathp,
712 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
713 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
714 if e != nil {
715 return e
716 }
717 defer Close(h)
718 a := Filetime{}
719 w := Filetime{}
720 if ts[0].Nsec != _UTIME_OMIT {
721 a = NsecToFiletime(TimespecToNsec(ts[0]))
722 }
723 if ts[1].Nsec != _UTIME_OMIT {
724 w = NsecToFiletime(TimespecToNsec(ts[1]))
725 }
726 return SetFileTime(h, nil, &a, &w)
727 }
728
729 func Fsync(fd Handle) (err error) {
730 return FlushFileBuffers(fd)
731 }
732
733 func Chmod(path string, mode uint32) (err error) {
734 p, e := UTF16PtrFromString(path)
735 if e != nil {
736 return e
737 }
738 attrs, e := GetFileAttributes(p)
739 if e != nil {
740 return e
741 }
742 if mode&S_IWRITE != 0 {
743 attrs &^= FILE_ATTRIBUTE_READONLY
744 } else {
745 attrs |= FILE_ATTRIBUTE_READONLY
746 }
747 return SetFileAttributes(p, attrs)
748 }
749
750 func LoadCancelIoEx() error {
751 return procCancelIoEx.Find()
752 }
753
754 func LoadSetFileCompletionNotificationModes() error {
755 return procSetFileCompletionNotificationModes.Find()
756 }
757
758
759
760 const socket_error = uintptr(^uint32(0))
761
762
763
764
765
766
767
768
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 var SocketDisableIPv6 bool
798
799 type RawSockaddrInet4 struct {
800 Family uint16
801 Port uint16
802 Addr [4]byte
803 Zero [8]uint8
804 }
805
806 type RawSockaddrInet6 struct {
807 Family uint16
808 Port uint16
809 Flowinfo uint32
810 Addr [16]byte
811 Scope_id uint32
812 }
813
814 type RawSockaddr struct {
815 Family uint16
816 Data [14]int8
817 }
818
819 type RawSockaddrAny struct {
820 Addr RawSockaddr
821 Pad [100]int8
822 }
823
824 type Sockaddr interface {
825 sockaddr() (ptr unsafe.Pointer, len int32, err error)
826 }
827
828 type SockaddrInet4 struct {
829 Port int
830 Addr [4]byte
831 raw RawSockaddrInet4
832 }
833
834 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
835 if sa.Port < 0 || sa.Port > 0xFFFF {
836 return nil, 0, EINVAL
837 }
838 sa.raw.Family = AF_INET
839 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
840 p[0] = byte(sa.Port >> 8)
841 p[1] = byte(sa.Port)
842 sa.raw.Addr = sa.Addr
843 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
844 }
845
846 type SockaddrInet6 struct {
847 Port int
848 ZoneId uint32
849 Addr [16]byte
850 raw RawSockaddrInet6
851 }
852
853 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
854 if sa.Port < 0 || sa.Port > 0xFFFF {
855 return nil, 0, EINVAL
856 }
857 sa.raw.Family = AF_INET6
858 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
859 p[0] = byte(sa.Port >> 8)
860 p[1] = byte(sa.Port)
861 sa.raw.Scope_id = sa.ZoneId
862 sa.raw.Addr = sa.Addr
863 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
864 }
865
866 type RawSockaddrUnix struct {
867 Family uint16
868 Path [UNIX_PATH_MAX]int8
869 }
870
871 type SockaddrUnix struct {
872 Name string
873 raw RawSockaddrUnix
874 }
875
876 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
877 name := sa.Name
878 n := len(name)
879 if n > len(sa.raw.Path) {
880 return nil, 0, EINVAL
881 }
882
883
884 isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
885
886
887
888 if n == len(sa.raw.Path) && !isAbstract {
889 return nil, 0, EINVAL
890 }
891 sa.raw.Family = AF_UNIX
892 for i := 0; i < n; i++ {
893 sa.raw.Path[i] = int8(name[i])
894 }
895
896
897 sl := int32(2 + n)
898 if isAbstract {
899
900
901 sa.raw.Path[0] = 0
902 } else if n > 0 {
903
904 sl++
905 }
906
907 return unsafe.Pointer(&sa.raw), sl, nil
908 }
909
910 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
911 switch rsa.Addr.Family {
912 case AF_UNIX:
913 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
914 sa := new(SockaddrUnix)
915 if pp.Path[0] == 0 {
916
917
918
919
920
921 pp.Path[0] = '@'
922 }
923
924
925
926
927
928
929 n := 0
930 for n < len(pp.Path) && pp.Path[n] != 0 {
931 n++
932 }
933 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
934 return sa, nil
935
936 case AF_INET:
937 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
938 sa := new(SockaddrInet4)
939 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
940 sa.Port = int(p[0])<<8 + int(p[1])
941 sa.Addr = pp.Addr
942 return sa, nil
943
944 case AF_INET6:
945 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
946 sa := new(SockaddrInet6)
947 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
948 sa.Port = int(p[0])<<8 + int(p[1])
949 sa.ZoneId = pp.Scope_id
950 sa.Addr = pp.Addr
951 return sa, nil
952 }
953 return nil, EAFNOSUPPORT
954 }
955
956 func Socket(domain, typ, proto int) (fd Handle, err error) {
957 if domain == AF_INET6 && SocketDisableIPv6 {
958 return InvalidHandle, EAFNOSUPPORT
959 }
960 return socket(int32(domain), int32(typ), int32(proto))
961 }
962
963 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
964 v := int32(value)
965 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
966 }
967
968 func Bind(fd Handle, sa Sockaddr) (err error) {
969 ptr, n, err := sa.sockaddr()
970 if err != nil {
971 return err
972 }
973 return bind(fd, ptr, n)
974 }
975
976 func Connect(fd Handle, sa Sockaddr) (err error) {
977 ptr, n, err := sa.sockaddr()
978 if err != nil {
979 return err
980 }
981 return connect(fd, ptr, n)
982 }
983
984 func Getsockname(fd Handle) (sa Sockaddr, err error) {
985 var rsa RawSockaddrAny
986 l := int32(unsafe.Sizeof(rsa))
987 if err = getsockname(fd, &rsa, &l); err != nil {
988 return
989 }
990 return rsa.Sockaddr()
991 }
992
993 func Getpeername(fd Handle) (sa Sockaddr, err error) {
994 var rsa RawSockaddrAny
995 l := int32(unsafe.Sizeof(rsa))
996 if err = getpeername(fd, &rsa, &l); err != nil {
997 return
998 }
999 return rsa.Sockaddr()
1000 }
1001
1002 func Listen(s Handle, n int) (err error) {
1003 return listen(s, int32(n))
1004 }
1005
1006 func Shutdown(fd Handle, how int) (err error) {
1007 return shutdown(fd, int32(how))
1008 }
1009
1010 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
1011 var rsa unsafe.Pointer
1012 var len int32
1013 if to != nil {
1014 rsa, len, err = to.sockaddr()
1015 if err != nil {
1016 return err
1017 }
1018 }
1019 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)))
1020 if r1 == socket_error {
1021 if e1 != 0 {
1022 err = errnoErr(e1)
1023 } else {
1024 err = EINVAL
1025 }
1026 }
1027 return err
1028 }
1029
1030 func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
1031 rsa, len, err := to.sockaddr()
1032 if err != nil {
1033 return err
1034 }
1035 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)))
1036 if r1 == socket_error {
1037 if e1 != 0 {
1038 err = errnoErr(e1)
1039 } else {
1040 err = EINVAL
1041 }
1042 }
1043 return err
1044 }
1045
1046 func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
1047 rsa, len, err := to.sockaddr()
1048 if err != nil {
1049 return err
1050 }
1051 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)))
1052 if r1 == socket_error {
1053 if e1 != 0 {
1054 err = errnoErr(e1)
1055 } else {
1056 err = EINVAL
1057 }
1058 }
1059 return err
1060 }
1061
1062 func LoadGetAddrInfo() error {
1063 return procGetAddrInfoW.Find()
1064 }
1065
1066 var connectExFunc struct {
1067 once sync.Once
1068 addr uintptr
1069 err error
1070 }
1071
1072 func LoadConnectEx() error {
1073 connectExFunc.once.Do(func() {
1074 var s Handle
1075 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1076 if connectExFunc.err != nil {
1077 return
1078 }
1079 defer CloseHandle(s)
1080 var n uint32
1081 connectExFunc.err = WSAIoctl(s,
1082 SIO_GET_EXTENSION_FUNCTION_POINTER,
1083 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
1084 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
1085 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
1086 uint32(unsafe.Sizeof(connectExFunc.addr)),
1087 &n, nil, 0)
1088 })
1089 return connectExFunc.err
1090 }
1091
1092 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
1093 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)
1094 if r1 == 0 {
1095 if e1 != 0 {
1096 err = error(e1)
1097 } else {
1098 err = EINVAL
1099 }
1100 }
1101 return
1102 }
1103
1104 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
1105 err := LoadConnectEx()
1106 if err != nil {
1107 return errorspkg.New("failed to find ConnectEx: " + err.Error())
1108 }
1109 ptr, n, err := sa.sockaddr()
1110 if err != nil {
1111 return err
1112 }
1113 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
1114 }
1115
1116
1117 type Rusage struct {
1118 CreationTime Filetime
1119 ExitTime Filetime
1120 KernelTime Filetime
1121 UserTime Filetime
1122 }
1123
1124 type WaitStatus struct {
1125 ExitCode uint32
1126 }
1127
1128 func (w WaitStatus) Exited() bool { return true }
1129
1130 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
1131
1132 func (w WaitStatus) Signal() Signal { return -1 }
1133
1134 func (w WaitStatus) CoreDump() bool { return false }
1135
1136 func (w WaitStatus) Stopped() bool { return false }
1137
1138 func (w WaitStatus) Continued() bool { return false }
1139
1140 func (w WaitStatus) StopSignal() Signal { return -1 }
1141
1142 func (w WaitStatus) Signaled() bool { return false }
1143
1144 func (w WaitStatus) TrapCause() int { return -1 }
1145
1146
1147
1148 type Timespec struct {
1149 Sec int64
1150 Nsec int64
1151 }
1152
1153 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1154
1155 func NsecToTimespec(nsec int64) (ts Timespec) {
1156 ts.Sec = nsec / 1e9
1157 ts.Nsec = nsec % 1e9
1158 return
1159 }
1160
1161
1162
1163 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1164 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1165 return 0, nil, EWINDOWS
1166 }
1167 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS }
1168 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1169
1170
1171
1172
1173
1174
1175
1176
1177 type Linger struct {
1178 Onoff int32
1179 Linger int32
1180 }
1181
1182 type sysLinger struct {
1183 Onoff uint16
1184 Linger uint16
1185 }
1186
1187 type IPMreq struct {
1188 Multiaddr [4]byte
1189 Interface [4]byte
1190 }
1191
1192 type IPv6Mreq struct {
1193 Multiaddr [16]byte
1194 Interface uint32
1195 }
1196
1197 func GetsockoptInt(fd Handle, level, opt int) (int, error) {
1198 optval := int32(0)
1199 optlen := int32(unsafe.Sizeof(optval))
1200 err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&optval)), &optlen)
1201 return int(optval), err
1202 }
1203
1204 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1205 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1206 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1207 }
1208
1209 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1210 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1211 }
1212 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1213 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1214 }
1215 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
1216 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1217 }
1218
1219 func Getpid() (pid int) { return int(getCurrentProcessId()) }
1220
1221 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1222
1223
1224
1225
1226
1227
1228
1229
1230 var data1 win32finddata1
1231 handle, err = findFirstFile1(name, &data1)
1232 if err == nil {
1233 copyFindData(data, &data1)
1234 }
1235 return
1236 }
1237
1238 func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1239 var data1 win32finddata1
1240 err = findNextFile1(handle, &data1)
1241 if err == nil {
1242 copyFindData(data, &data1)
1243 }
1244 return
1245 }
1246
1247 func getProcessEntry(pid int) (*ProcessEntry32, error) {
1248 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1249 if err != nil {
1250 return nil, err
1251 }
1252 defer CloseHandle(snapshot)
1253 var procEntry ProcessEntry32
1254 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1255 if err = Process32First(snapshot, &procEntry); err != nil {
1256 return nil, err
1257 }
1258 for {
1259 if procEntry.ProcessID == uint32(pid) {
1260 return &procEntry, nil
1261 }
1262 err = Process32Next(snapshot, &procEntry)
1263 if err != nil {
1264 return nil, err
1265 }
1266 }
1267 }
1268
1269 func Getppid() (ppid int) {
1270 pe, err := getProcessEntry(Getpid())
1271 if err != nil {
1272 return -1
1273 }
1274 return int(pe.ParentProcessID)
1275 }
1276
1277 func fdpath(fd Handle, buf []uint16) ([]uint16, error) {
1278 const (
1279 FILE_NAME_NORMALIZED = 0
1280 VOLUME_NAME_DOS = 0
1281 )
1282 for {
1283 n, err := getFinalPathNameByHandle(fd, &buf[0], uint32(len(buf)), FILE_NAME_NORMALIZED|VOLUME_NAME_DOS)
1284 if err == nil {
1285 buf = buf[:n]
1286 break
1287 }
1288 if err != _ERROR_NOT_ENOUGH_MEMORY {
1289 return nil, err
1290 }
1291 buf = append(buf, make([]uint16, n-uint32(len(buf)))...)
1292 }
1293 return buf, nil
1294 }
1295
1296 func Fchdir(fd Handle) (err error) {
1297 var buf [MAX_PATH + 1]uint16
1298 path, err := fdpath(fd, buf[:])
1299 if err != nil {
1300 return err
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 if len(path) >= 4 && path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\' {
1312 path = path[4:]
1313 }
1314 return SetCurrentDirectory(&path[0])
1315 }
1316
1317
1318 func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1319 func Symlink(path, link string) (err error) { return EWINDOWS }
1320
1321 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
1322 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
1323 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1324 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS }
1325
1326 func Getuid() (uid int) { return -1 }
1327 func Geteuid() (euid int) { return -1 }
1328 func Getgid() (gid int) { return -1 }
1329 func Getegid() (egid int) { return -1 }
1330 func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1331
1332 type Signal int
1333
1334 func (s Signal) Signal() {}
1335
1336 func (s Signal) String() string {
1337 if 0 <= s && int(s) < len(signals) {
1338 str := signals[s]
1339 if str != "" {
1340 return str
1341 }
1342 }
1343 return "signal " + itoa.Itoa(int(s))
1344 }
1345
1346 func LoadCreateSymbolicLink() error {
1347 return procCreateSymbolicLinkW.Find()
1348 }
1349
1350
1351 func Readlink(path string, buf []byte) (n int, err error) {
1352 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1353 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1354 if err != nil {
1355 return -1, err
1356 }
1357 defer CloseHandle(fd)
1358
1359 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1360 var bytesReturned uint32
1361 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1362 if err != nil {
1363 return -1, err
1364 }
1365
1366 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1367 var s string
1368 switch rdb.ReparseTag {
1369 case IO_REPARSE_TAG_SYMLINK:
1370 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1371 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1372 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1373 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1374 if len(s) >= 4 && s[:4] == `\??\` {
1375 s = s[4:]
1376 switch {
1377 case len(s) >= 2 && s[1] == ':':
1378
1379 case len(s) >= 4 && s[:4] == `UNC\`:
1380 s = `\\` + s[4:]
1381 default:
1382
1383 }
1384 } else {
1385
1386 }
1387 }
1388 case _IO_REPARSE_TAG_MOUNT_POINT:
1389 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1390 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1391 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1392 if len(s) >= 4 && s[:4] == `\??\` {
1393 s = s[4:]
1394 } else {
1395
1396 }
1397 default:
1398
1399
1400 return -1, ENOENT
1401 }
1402 n = copy(buf, []byte(s))
1403
1404 return n, nil
1405 }
1406
1407
1408 func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1409 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1410 }
1411
1412
1413 func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1414 var ukey uintptr
1415 var pukey *uintptr
1416 if key != nil {
1417 ukey = uintptr(*key)
1418 pukey = &ukey
1419 }
1420 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1421 if key != nil {
1422 *key = uint32(ukey)
1423 if uintptr(*key) != ukey && err == nil {
1424 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1425 }
1426 }
1427 return err
1428 }
1429
1430
1431 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1432 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1433 }
1434
1435
1436 func newProcThreadAttributeList(maxAttrCount uint32) (*procThreadAttributeListContainer, error) {
1437 var size uintptr
1438 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1439 if err != ERROR_INSUFFICIENT_BUFFER {
1440 if err == nil {
1441 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1442 }
1443 return nil, err
1444 }
1445 const LMEM_FIXED = 0
1446 alloc, err := localAlloc(LMEM_FIXED, uint32(size))
1447 if err != nil {
1448 return nil, err
1449 }
1450
1451 al := &procThreadAttributeListContainer{data: (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(alloc))}
1452 err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size)
1453 if err != nil {
1454 return nil, err
1455 }
1456 al.pointers = make([]unsafe.Pointer, 0, maxAttrCount)
1457 return al, err
1458 }
1459
1460
1461 func (al *procThreadAttributeListContainer) update(attribute uintptr, value unsafe.Pointer, size uintptr) error {
1462 al.pointers = append(al.pointers, value)
1463 return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil)
1464 }
1465
1466
1467 func (al *procThreadAttributeListContainer) delete() {
1468 deleteProcThreadAttributeList(al.data)
1469 LocalFree(Handle(unsafe.Pointer(al.data)))
1470 al.data = nil
1471 al.pointers = nil
1472 }
1473
1474
1475 func (al *procThreadAttributeListContainer) list() *_PROC_THREAD_ATTRIBUTE_LIST {
1476 return al.data
1477 }
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503 func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1504 return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1505 }
1506
1507 func GetStartupInfo(startupInfo *StartupInfo) error {
1508 getStartupInfo(startupInfo)
1509 return nil
1510 }
1511
1512 func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
1513 handle, err = createFile(name, access, mode, sa, createmode, attrs, templatefile)
1514 if handle != InvalidHandle {
1515
1516
1517 err = nil
1518 }
1519 return handle, err
1520 }
1521
View as plain text