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