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