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