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