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