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 if n == len(sa.raw.Path) && name[0] != '@' {
862 return nil, 0, EINVAL
863 }
864 sa.raw.Family = AF_UNIX
865 for i := 0; i < n; i++ {
866 sa.raw.Path[i] = int8(name[i])
867 }
868
869 sl := int32(2)
870 if n > 0 {
871 sl += int32(n) + 1
872 }
873 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
874
875 sa.raw.Path[0] = 0
876
877 sl--
878 }
879
880 return unsafe.Pointer(&sa.raw), sl, nil
881 }
882
883 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
884 switch rsa.Addr.Family {
885 case AF_UNIX:
886 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
887 sa := new(SockaddrUnix)
888 if pp.Path[0] == 0 {
889
890
891
892
893
894 pp.Path[0] = '@'
895 }
896
897
898
899
900
901
902 n := 0
903 for n < len(pp.Path) && pp.Path[n] != 0 {
904 n++
905 }
906 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
907 return sa, nil
908
909 case AF_INET:
910 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
911 sa := new(SockaddrInet4)
912 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
913 sa.Port = int(p[0])<<8 + int(p[1])
914 sa.Addr = pp.Addr
915 return sa, nil
916
917 case AF_INET6:
918 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
919 sa := new(SockaddrInet6)
920 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
921 sa.Port = int(p[0])<<8 + int(p[1])
922 sa.ZoneId = pp.Scope_id
923 sa.Addr = pp.Addr
924 return sa, nil
925 }
926 return nil, EAFNOSUPPORT
927 }
928
929 func Socket(domain, typ, proto int) (fd Handle, err error) {
930 if domain == AF_INET6 && SocketDisableIPv6 {
931 return InvalidHandle, EAFNOSUPPORT
932 }
933 return socket(int32(domain), int32(typ), int32(proto))
934 }
935
936 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
937 v := int32(value)
938 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
939 }
940
941 func Bind(fd Handle, sa Sockaddr) (err error) {
942 ptr, n, err := sa.sockaddr()
943 if err != nil {
944 return err
945 }
946 return bind(fd, ptr, n)
947 }
948
949 func Connect(fd Handle, sa Sockaddr) (err error) {
950 ptr, n, err := sa.sockaddr()
951 if err != nil {
952 return err
953 }
954 return connect(fd, ptr, n)
955 }
956
957 func Getsockname(fd Handle) (sa Sockaddr, err error) {
958 var rsa RawSockaddrAny
959 l := int32(unsafe.Sizeof(rsa))
960 if err = getsockname(fd, &rsa, &l); err != nil {
961 return
962 }
963 return rsa.Sockaddr()
964 }
965
966 func Getpeername(fd Handle) (sa Sockaddr, err error) {
967 var rsa RawSockaddrAny
968 l := int32(unsafe.Sizeof(rsa))
969 if err = getpeername(fd, &rsa, &l); err != nil {
970 return
971 }
972 return rsa.Sockaddr()
973 }
974
975 func Listen(s Handle, n int) (err error) {
976 return listen(s, int32(n))
977 }
978
979 func Shutdown(fd Handle, how int) (err error) {
980 return shutdown(fd, int32(how))
981 }
982
983 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
984 var rsa unsafe.Pointer
985 var len int32
986 if to != nil {
987 rsa, len, err = to.sockaddr()
988 if err != nil {
989 return err
990 }
991 }
992 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)))
993 if r1 == socket_error {
994 if e1 != 0 {
995 err = errnoErr(e1)
996 } else {
997 err = EINVAL
998 }
999 }
1000 return err
1001 }
1002
1003 func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
1004 rsa, len, err := to.sockaddr()
1005 if err != nil {
1006 return err
1007 }
1008 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)))
1009 if r1 == socket_error {
1010 if e1 != 0 {
1011 err = errnoErr(e1)
1012 } else {
1013 err = EINVAL
1014 }
1015 }
1016 return err
1017 }
1018
1019 func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
1020 rsa, len, err := to.sockaddr()
1021 if err != nil {
1022 return err
1023 }
1024 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)))
1025 if r1 == socket_error {
1026 if e1 != 0 {
1027 err = errnoErr(e1)
1028 } else {
1029 err = EINVAL
1030 }
1031 }
1032 return err
1033 }
1034
1035 func LoadGetAddrInfo() error {
1036 return procGetAddrInfoW.Find()
1037 }
1038
1039 var connectExFunc struct {
1040 once sync.Once
1041 addr uintptr
1042 err error
1043 }
1044
1045 func LoadConnectEx() error {
1046 connectExFunc.once.Do(func() {
1047 var s Handle
1048 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1049 if connectExFunc.err != nil {
1050 return
1051 }
1052 defer CloseHandle(s)
1053 var n uint32
1054 connectExFunc.err = WSAIoctl(s,
1055 SIO_GET_EXTENSION_FUNCTION_POINTER,
1056 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
1057 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
1058 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
1059 uint32(unsafe.Sizeof(connectExFunc.addr)),
1060 &n, nil, 0)
1061 })
1062 return connectExFunc.err
1063 }
1064
1065 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
1066 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)
1067 if r1 == 0 {
1068 if e1 != 0 {
1069 err = error(e1)
1070 } else {
1071 err = EINVAL
1072 }
1073 }
1074 return
1075 }
1076
1077 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
1078 err := LoadConnectEx()
1079 if err != nil {
1080 return errorspkg.New("failed to find ConnectEx: " + err.Error())
1081 }
1082 ptr, n, err := sa.sockaddr()
1083 if err != nil {
1084 return err
1085 }
1086 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
1087 }
1088
1089
1090 type Rusage struct {
1091 CreationTime Filetime
1092 ExitTime Filetime
1093 KernelTime Filetime
1094 UserTime Filetime
1095 }
1096
1097 type WaitStatus struct {
1098 ExitCode uint32
1099 }
1100
1101 func (w WaitStatus) Exited() bool { return true }
1102
1103 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
1104
1105 func (w WaitStatus) Signal() Signal { return -1 }
1106
1107 func (w WaitStatus) CoreDump() bool { return false }
1108
1109 func (w WaitStatus) Stopped() bool { return false }
1110
1111 func (w WaitStatus) Continued() bool { return false }
1112
1113 func (w WaitStatus) StopSignal() Signal { return -1 }
1114
1115 func (w WaitStatus) Signaled() bool { return false }
1116
1117 func (w WaitStatus) TrapCause() int { return -1 }
1118
1119
1120
1121 type Timespec struct {
1122 Sec int64
1123 Nsec int64
1124 }
1125
1126 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1127
1128 func NsecToTimespec(nsec int64) (ts Timespec) {
1129 ts.Sec = nsec / 1e9
1130 ts.Nsec = nsec % 1e9
1131 return
1132 }
1133
1134
1135
1136 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1137 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1138 return 0, nil, EWINDOWS
1139 }
1140 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS }
1141 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1142
1143
1144
1145
1146
1147
1148
1149
1150 type Linger struct {
1151 Onoff int32
1152 Linger int32
1153 }
1154
1155 type sysLinger struct {
1156 Onoff uint16
1157 Linger uint16
1158 }
1159
1160 type IPMreq struct {
1161 Multiaddr [4]byte
1162 Interface [4]byte
1163 }
1164
1165 type IPv6Mreq struct {
1166 Multiaddr [16]byte
1167 Interface uint32
1168 }
1169
1170 func GetsockoptInt(fd Handle, level, opt int) (int, error) {
1171 optval := int32(0)
1172 optlen := int32(unsafe.Sizeof(optval))
1173 err := Getsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&optval)), &optlen)
1174 return int(optval), err
1175 }
1176
1177 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1178 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1179 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1180 }
1181
1182 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1183 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1184 }
1185 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1186 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1187 }
1188 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
1189
1190 func Getpid() (pid int) { return int(getCurrentProcessId()) }
1191
1192 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1193
1194
1195
1196
1197
1198
1199
1200
1201 var data1 win32finddata1
1202 handle, err = findFirstFile1(name, &data1)
1203 if err == nil {
1204 copyFindData(data, &data1)
1205 }
1206 return
1207 }
1208
1209 func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1210 var data1 win32finddata1
1211 err = findNextFile1(handle, &data1)
1212 if err == nil {
1213 copyFindData(data, &data1)
1214 }
1215 return
1216 }
1217
1218 func getProcessEntry(pid int) (*ProcessEntry32, error) {
1219 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1220 if err != nil {
1221 return nil, err
1222 }
1223 defer CloseHandle(snapshot)
1224 var procEntry ProcessEntry32
1225 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1226 if err = Process32First(snapshot, &procEntry); err != nil {
1227 return nil, err
1228 }
1229 for {
1230 if procEntry.ProcessID == uint32(pid) {
1231 return &procEntry, nil
1232 }
1233 err = Process32Next(snapshot, &procEntry)
1234 if err != nil {
1235 return nil, err
1236 }
1237 }
1238 }
1239
1240 func Getppid() (ppid int) {
1241 pe, err := getProcessEntry(Getpid())
1242 if err != nil {
1243 return -1
1244 }
1245 return int(pe.ParentProcessID)
1246 }
1247
1248 func fdpath(fd Handle, buf []uint16) ([]uint16, error) {
1249 const (
1250 FILE_NAME_NORMALIZED = 0
1251 VOLUME_NAME_DOS = 0
1252 )
1253 for {
1254 n, err := getFinalPathNameByHandle(fd, &buf[0], uint32(len(buf)), FILE_NAME_NORMALIZED|VOLUME_NAME_DOS)
1255 if err == nil {
1256 buf = buf[:n]
1257 break
1258 }
1259 if err != _ERROR_NOT_ENOUGH_MEMORY {
1260 return nil, err
1261 }
1262 buf = append(buf, make([]uint16, n-uint32(len(buf)))...)
1263 }
1264 return buf, nil
1265 }
1266
1267 func Fchdir(fd Handle) (err error) {
1268 var buf [MAX_PATH + 1]uint16
1269 path, err := fdpath(fd, buf[:])
1270 if err != nil {
1271 return err
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282 if len(path) >= 4 && path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\' {
1283 path = path[4:]
1284 }
1285 return SetCurrentDirectory(&path[0])
1286 }
1287
1288
1289 func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1290 func Symlink(path, link string) (err error) { return EWINDOWS }
1291
1292 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
1293 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
1294 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1295 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS }
1296
1297 func Getuid() (uid int) { return -1 }
1298 func Geteuid() (euid int) { return -1 }
1299 func Getgid() (gid int) { return -1 }
1300 func Getegid() (egid int) { return -1 }
1301 func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1302
1303 type Signal int
1304
1305 func (s Signal) Signal() {}
1306
1307 func (s Signal) String() string {
1308 if 0 <= s && int(s) < len(signals) {
1309 str := signals[s]
1310 if str != "" {
1311 return str
1312 }
1313 }
1314 return "signal " + itoa.Itoa(int(s))
1315 }
1316
1317 func LoadCreateSymbolicLink() error {
1318 return procCreateSymbolicLinkW.Find()
1319 }
1320
1321
1322 func Readlink(path string, buf []byte) (n int, err error) {
1323 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1324 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1325 if err != nil {
1326 return -1, err
1327 }
1328 defer CloseHandle(fd)
1329
1330 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1331 var bytesReturned uint32
1332 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1333 if err != nil {
1334 return -1, err
1335 }
1336
1337 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1338 var s string
1339 switch rdb.ReparseTag {
1340 case IO_REPARSE_TAG_SYMLINK:
1341 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1342 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1343 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1344 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1345 if len(s) >= 4 && s[:4] == `\??\` {
1346 s = s[4:]
1347 switch {
1348 case len(s) >= 2 && s[1] == ':':
1349
1350 case len(s) >= 4 && s[:4] == `UNC\`:
1351 s = `\\` + s[4:]
1352 default:
1353
1354 }
1355 } else {
1356
1357 }
1358 }
1359 case _IO_REPARSE_TAG_MOUNT_POINT:
1360 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1361 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1362 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1363 if len(s) >= 4 && s[:4] == `\??\` {
1364 s = s[4:]
1365 } else {
1366
1367 }
1368 default:
1369
1370
1371 return -1, ENOENT
1372 }
1373 n = copy(buf, []byte(s))
1374
1375 return n, nil
1376 }
1377
1378
1379 func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1380 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1381 }
1382
1383
1384 func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1385 var ukey uintptr
1386 var pukey *uintptr
1387 if key != nil {
1388 ukey = uintptr(*key)
1389 pukey = &ukey
1390 }
1391 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1392 if key != nil {
1393 *key = uint32(ukey)
1394 if uintptr(*key) != ukey && err == nil {
1395 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1396 }
1397 }
1398 return err
1399 }
1400
1401
1402 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1403 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1404 }
1405
1406
1407
1408
1409 func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) {
1410 var size uintptr
1411 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1412 if err != ERROR_INSUFFICIENT_BUFFER {
1413 if err == nil {
1414 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1415 }
1416 return nil, err
1417 }
1418
1419 al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
1420 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
1421 if err != nil {
1422 return nil, err
1423 }
1424 return al, nil
1425 }
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451 func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1452 return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1453 }
1454
1455 func GetStartupInfo(startupInfo *StartupInfo) error {
1456 getStartupInfo(startupInfo)
1457 return nil
1458 }
1459
1460 func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
1461 handle, err = createFile(name, access, mode, sa, createmode, attrs, templatefile)
1462 if handle != InvalidHandle {
1463
1464
1465 err = nil
1466 }
1467 return handle, err
1468 }
1469
View as plain text